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