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