secdig.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. #include "secdig.h"
  5. #include "secoid.h"
  6. #include "secasn1.h"
  7. #include "secerr.h"
  8. /*
  9. * XXX Want to have a SGN_DecodeDigestInfo, like:
  10. * SGNDigestInfo *SGN_DecodeDigestInfo(SECItem *didata);
  11. * that creates a pool and allocates from it and decodes didata into
  12. * the newly allocated DigestInfo structure. Then fix secvfy.c (it
  13. * will no longer need an arena itself) to call this and then call
  14. * DestroyDigestInfo when it is done, then can remove the old template
  15. * above and keep our new template static and "hidden".
  16. */
  17. /*
  18. * XXX It might be nice to combine the following two functions (create
  19. * and encode). I think that is all anybody ever wants to do anyway.
  20. */
  21. SECItem *
  22. SGN_EncodeDigestInfo(PLArenaPool *poolp, SECItem *dest, SGNDigestInfo *diginfo)
  23. {
  24. return SEC_ASN1EncodeItem(poolp, dest, diginfo, sgn_DigestInfoTemplate);
  25. }
  26. SGNDigestInfo *
  27. SGN_CreateDigestInfo(SECOidTag algorithm, const unsigned char *sig,
  28. unsigned len)
  29. {
  30. SGNDigestInfo *di;
  31. SECStatus rv;
  32. PLArenaPool *arena;
  33. SECItem *null_param;
  34. SECItem dummy_value;
  35. switch (algorithm) {
  36. case SEC_OID_MD2:
  37. case SEC_OID_MD5:
  38. case SEC_OID_SHA1:
  39. case SEC_OID_SHA224:
  40. case SEC_OID_SHA256:
  41. case SEC_OID_SHA384:
  42. case SEC_OID_SHA512:
  43. break;
  44. default:
  45. PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
  46. return NULL;
  47. }
  48. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  49. if (arena == NULL) {
  50. return NULL;
  51. }
  52. di = (SGNDigestInfo *)PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
  53. if (di == NULL) {
  54. PORT_FreeArena(arena, PR_FALSE);
  55. return NULL;
  56. }
  57. di->arena = arena;
  58. /*
  59. * PKCS #1 specifies that the AlgorithmID must have a NULL parameter
  60. * (as opposed to no parameter at all).
  61. */
  62. dummy_value.data = NULL;
  63. dummy_value.len = 0;
  64. null_param = SEC_ASN1EncodeItem(NULL, NULL, &dummy_value, SEC_NullTemplate);
  65. if (null_param == NULL) {
  66. goto loser;
  67. }
  68. rv = SECOID_SetAlgorithmID(arena, &di->digestAlgorithm, algorithm,
  69. null_param);
  70. SECITEM_FreeItem(null_param, PR_TRUE);
  71. if (rv != SECSuccess) {
  72. goto loser;
  73. }
  74. di->digest.data = (unsigned char *)PORT_ArenaAlloc(arena, len);
  75. if (di->digest.data == NULL) {
  76. goto loser;
  77. }
  78. di->digest.len = len;
  79. PORT_Memcpy(di->digest.data, sig, len);
  80. return di;
  81. loser:
  82. SGN_DestroyDigestInfo(di);
  83. return NULL;
  84. }
  85. SGNDigestInfo *
  86. SGN_DecodeDigestInfo(SECItem *didata)
  87. {
  88. PLArenaPool *arena;
  89. SGNDigestInfo *di;
  90. SECStatus rv = SECFailure;
  91. SECItem diCopy = { siBuffer, NULL, 0 };
  92. arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
  93. if (arena == NULL)
  94. return NULL;
  95. rv = SECITEM_CopyItem(arena, &diCopy, didata);
  96. if (rv != SECSuccess) {
  97. PORT_FreeArena(arena, PR_FALSE);
  98. return NULL;
  99. }
  100. di = (SGNDigestInfo *)PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
  101. if (di != NULL) {
  102. di->arena = arena;
  103. rv = SEC_QuickDERDecodeItem(arena, di, sgn_DigestInfoTemplate, &diCopy);
  104. }
  105. if ((di == NULL) || (rv != SECSuccess)) {
  106. PORT_FreeArena(arena, PR_FALSE);
  107. di = NULL;
  108. }
  109. return di;
  110. }
  111. void
  112. SGN_DestroyDigestInfo(SGNDigestInfo *di)
  113. {
  114. if (di && di->arena) {
  115. PORT_FreeArena(di->arena, PR_FALSE);
  116. }
  117. return;
  118. }
  119. SECStatus
  120. SGN_CopyDigestInfo(PLArenaPool *poolp, SGNDigestInfo *a, SGNDigestInfo *b)
  121. {
  122. SECStatus rv;
  123. void *mark;
  124. if ((poolp == NULL) || (a == NULL) || (b == NULL))
  125. return SECFailure;
  126. mark = PORT_ArenaMark(poolp);
  127. a->arena = poolp;
  128. rv = SECOID_CopyAlgorithmID(poolp, &a->digestAlgorithm,
  129. &b->digestAlgorithm);
  130. if (rv == SECSuccess)
  131. rv = SECITEM_CopyItem(poolp, &a->digest, &b->digest);
  132. if (rv != SECSuccess) {
  133. PORT_ArenaRelease(poolp, mark);
  134. } else {
  135. PORT_ArenaUnmark(poolp, mark);
  136. }
  137. return rv;
  138. }
  139. SECComparison
  140. SGN_CompareDigestInfo(SGNDigestInfo *a, SGNDigestInfo *b)
  141. {
  142. SECComparison rv;
  143. /* Check signature algorithm's */
  144. rv = SECOID_CompareAlgorithmID(&a->digestAlgorithm, &b->digestAlgorithm);
  145. if (rv)
  146. return rv;
  147. /* Compare signature block length's */
  148. rv = SECITEM_CompareItem(&a->digest, &b->digest);
  149. return rv;
  150. }