| 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 "cryptohi.h" | |
| 5 #include "secasn1.h" | |
| 6 #include "secitem.h" | |
| 7 #include "prerr.h" | |
| 8 | |
| 9 #ifndef DSA1_SUBPRIME_LEN | |
| 10 #define DSA1_SUBPRIME_LEN 20 /* bytes */ | |
| 11 #endif | |
| 12 | |
| 13 typedef struct { | |
| 14 SECItem r; | |
| 15 SECItem s; | |
| 16 } DSA_ASN1Signature; | |
| 17 | |
| 18 const SEC_ASN1Template DSA_SignatureTemplate[] = | |
| 19 { | |
| 20 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(DSA_ASN1Signature) }, | |
| 21 { SEC_ASN1_INTEGER, offsetof(DSA_ASN1Signature, r) }, | |
| 22 { SEC_ASN1_INTEGER, offsetof(DSA_ASN1Signature, s) }, | |
| 23 { 0 } | |
| 24 }; | |
| 25 | |
| 26 /* Input is variable length multi-byte integer, MSB first (big endian). | |
| 27 ** Most signficant bit of first byte is NOT treated as a sign bit. | |
| 28 ** May be one or more leading bytes of zeros. | |
| 29 ** Output is variable length multi-byte integer, MSB first (big endian). | |
| 30 ** Most significant bit of first byte will be zero (positive sign bit) | |
| 31 ** No more than one leading zero byte. | |
| 32 ** Caller supplies dest buffer, and assures that it is long enough, | |
| 33 ** e.g. at least one byte longer that src's buffer. | |
| 34 */ | |
| 35 void | |
| 36 DSAU_ConvertUnsignedToSigned(SECItem *dest, SECItem *src) | |
| 37 { | |
| 38 unsigned char *pSrc = src->data; | |
| 39 unsigned char *pDst = dest->data; | |
| 40 unsigned int cntSrc = src->len; | |
| 41 | |
| 42 /* skip any leading zeros. */ | |
| 43 while (cntSrc && !(*pSrc)) { | |
| 44 pSrc++; | |
| 45 cntSrc--; | |
| 46 } | |
| 47 if (!cntSrc) { | |
| 48 *pDst = 0; | |
| 49 dest->len = 1; | |
| 50 return; | |
| 51 } | |
| 52 | |
| 53 if (*pSrc & 0x80) | |
| 54 *pDst++ = 0; | |
| 55 | |
| 56 PORT_Memcpy(pDst, pSrc, cntSrc); | |
| 57 dest->len = (pDst - dest->data) + cntSrc; | |
| 58 } | |
| 59 | |
| 60 /* | |
| 61 ** src is a buffer holding a signed variable length integer. | |
| 62 ** dest is a buffer which will be filled with an unsigned integer, | |
| 63 ** MSB first (big endian) with leading zeros, so that the last byte | |
| 64 ** of src will be the LSB of the integer. The result will be exactly | |
| 65 ** the length specified by the caller in dest->len. | |
| 66 ** src can be shorter than dest. src can be longer than dst, but only | |
| 67 ** if the extra leading bytes are zeros. | |
| 68 */ | |
| 69 SECStatus | |
| 70 DSAU_ConvertSignedToFixedUnsigned(SECItem *dest, SECItem *src) | |
| 71 { | |
| 72 unsigned char *pSrc = src->data; | |
| 73 unsigned char *pDst = dest->data; | |
| 74 unsigned int cntSrc = src->len; | |
| 75 unsigned int cntDst = dest->len; | |
| 76 int zCount = cntDst - cntSrc; | |
| 77 | |
| 78 if (zCount > 0) { | |
| 79 PORT_Memset(pDst, 0, zCount); | |
| 80 PORT_Memcpy(pDst + zCount, pSrc, cntSrc); | |
| 81 return SECSuccess; | |
| 82 } | |
| 83 if (zCount <= 0) { | |
| 84 /* Source is longer than destination. Check for leading zeros. */ | |
| 85 while (zCount++ < 0) { | |
| 86 if (*pSrc++ != 0) | |
| 87 goto loser; | |
| 88 } | |
| 89 } | |
| 90 PORT_Memcpy(pDst, pSrc, cntDst); | |
| 91 return SECSuccess; | |
| 92 | |
| 93 loser: | |
| 94 PORT_SetError(PR_INVALID_ARGUMENT_ERROR); | |
| 95 return SECFailure; | |
| 96 } | |
| 97 | |
| 98 /* src is a "raw" ECDSA or DSA signature, the first half contains r | |
| 99 * and the second half contains s. dest is the DER encoded signature. | |
| 100 */ | |
| 101 static SECStatus | |
| 102 common_EncodeDerSig(SECItem *dest, SECItem *src) | |
| 103 { | |
| 104 SECItem *item; | |
| 105 SECItem srcItem; | |
| 106 DSA_ASN1Signature sig; | |
| 107 unsigned char *signedR; | |
| 108 unsigned char *signedS; | |
| 109 unsigned int len; | |
| 110 | |
| 111 /* Allocate memory with room for an extra byte that | |
| 112 * may be required if the top bit in the first byte | |
| 113 * is already set. | |
| 114 */ | |
| 115 len = src->len / 2; | |
| 116 signedR = (unsigned char *)PORT_Alloc(len + 1); | |
| 117 if (!signedR) | |
| 118 return SECFailure; | |
| 119 signedS = (unsigned char *)PORT_ZAlloc(len + 1); | |
| 120 if (!signedS) { | |
| 121 if (signedR) | |
| 122 PORT_Free(signedR); | |
| 123 return SECFailure; | |
| 124 } | |
| 125 | |
| 126 PORT_Memset(&sig, 0, sizeof(sig)); | |
| 127 | |
| 128 /* Must convert r and s from "unsigned" integers to "signed" integers. | |
| 129 ** If the high order bit of the first byte (MSB) is 1, then must | |
| 130 ** prepend with leading zero. | |
| 131 ** Must remove all but one leading zero byte from numbers. | |
| 132 */ | |
| 133 sig.r.type = siUnsignedInteger; | |
| 134 sig.r.data = signedR; | |
| 135 sig.r.len = sizeof signedR; | |
| 136 sig.s.type = siUnsignedInteger; | |
| 137 sig.s.data = signedS; | |
| 138 sig.s.len = sizeof signedR; | |
| 139 | |
| 140 srcItem.data = src->data; | |
| 141 srcItem.len = len; | |
| 142 | |
| 143 DSAU_ConvertUnsignedToSigned(&sig.r, &srcItem); | |
| 144 srcItem.data += len; | |
| 145 DSAU_ConvertUnsignedToSigned(&sig.s, &srcItem); | |
| 146 | |
| 147 item = SEC_ASN1EncodeItem(NULL, dest, &sig, DSA_SignatureTemplate); | |
| 148 if (signedR) | |
| 149 PORT_Free(signedR); | |
| 150 if (signedS) | |
| 151 PORT_Free(signedS); | |
| 152 if (item == NULL) | |
| 153 return SECFailure; | |
| 154 | |
| 155 /* XXX leak item? */ | |
| 156 return SECSuccess; | |
| 157 } | |
| 158 | |
| 159 /* src is a DER-encoded ECDSA or DSA signature. | |
| 160 ** Returns a newly-allocated SECItem structure, pointing at a newly allocated | |
| 161 ** buffer containing the "raw" signature, which is len bytes of r, | |
| 162 ** followed by len bytes of s. For DSA, len is the length of q. | |
| 163 ** For ECDSA, len depends on the key size used to create the signature. | |
| 164 */ | |
| 165 static SECItem * | |
| 166 common_DecodeDerSig(const SECItem *item, unsigned int len) | |
| 167 { | |
| 168 SECItem *result = NULL; | |
| 169 SECStatus status; | |
| 170 DSA_ASN1Signature sig; | |
| 171 SECItem dst; | |
| 172 | |
| 173 PORT_Memset(&sig, 0, sizeof(sig)); | |
| 174 | |
| 175 result = PORT_ZNew(SECItem); | |
| 176 if (result == NULL) | |
| 177 goto loser; | |
| 178 | |
| 179 result->len = 2 * len; | |
| 180 result->data = (unsigned char *)PORT_Alloc(2 * len); | |
| 181 if (result->data == NULL) | |
| 182 goto loser; | |
| 183 | |
| 184 sig.r.type = siUnsignedInteger; | |
| 185 sig.s.type = siUnsignedInteger; | |
| 186 status = SEC_ASN1DecodeItem(NULL, &sig, DSA_SignatureTemplate, item); | |
| 187 if (status != SECSuccess) | |
| 188 goto loser; | |
| 189 | |
| 190 /* Convert sig.r and sig.s from variable length signed integers to | |
| 191 ** fixed length unsigned integers. | |
| 192 */ | |
| 193 dst.data = result->data; | |
| 194 dst.len = len; | |
| 195 status = DSAU_ConvertSignedToFixedUnsigned(&dst, &sig.r); | |
| 196 if (status != SECSuccess) | |
| 197 goto loser; | |
| 198 | |
| 199 dst.data += len; | |
| 200 status = DSAU_ConvertSignedToFixedUnsigned(&dst, &sig.s); | |
| 201 if (status != SECSuccess) | |
| 202 goto loser; | |
| 203 | |
| 204 done: | |
| 205 if (sig.r.data != NULL) | |
| 206 PORT_Free(sig.r.data); | |
| 207 if (sig.s.data != NULL) | |
| 208 PORT_Free(sig.s.data); | |
| 209 | |
| 210 return result; | |
| 211 | |
| 212 loser: | |
| 213 if (result != NULL) { | |
| 214 SECITEM_FreeItem(result, PR_TRUE); | |
| 215 result = NULL; | |
| 216 } | |
| 217 goto done; | |
| 218 } | |
| 219 | |
| 220 /* src is a "raw" DSA1 signature, 20 bytes of r followed by 20 bytes of s. | |
| 221 ** dest is the signature DER encoded. ? | |
| 222 */ | |
| 223 SECStatus | |
| 224 DSAU_EncodeDerSig(SECItem *dest, SECItem *src) | |
| 225 { | |
| 226 PORT_Assert(src->len == 2 * DSA1_SUBPRIME_LEN); | |
| 227 if (src->len != 2 * DSA1_SUBPRIME_LEN) { | |
| 228 PORT_SetError(PR_INVALID_ARGUMENT_ERROR); | |
| 229 return SECFailure; | |
| 230 } | |
| 231 | |
| 232 return common_EncodeDerSig(dest, src); | |
| 233 } | |
| 234 | |
| 235 /* src is a "raw" DSA signature of length len (len/2 bytes of r followed | |
| 236 ** by len/2 bytes of s). dest is the signature DER encoded. | |
| 237 */ | |
| 238 SECStatus | |
| 239 DSAU_EncodeDerSigWithLen(SECItem *dest, SECItem *src, unsigned int len) | |
| 240 { | |
| 241 | |
| 242 PORT_Assert((src->len == len) && (len % 2 == 0)); | |
| 243 if ((src->len != len) || (src->len % 2 != 0)) { | |
| 244 PORT_SetError(PR_INVALID_ARGUMENT_ERROR); | |
| 245 return SECFailure; | |
| 246 } | |
| 247 | |
| 248 return common_EncodeDerSig(dest, src); | |
| 249 } | |
| 250 | |
| 251 /* src is a DER-encoded DSA signature. | |
| 252 ** Returns a newly-allocated SECItem structure, pointing at a newly allocated | |
| 253 ** buffer containing the "raw" DSA1 signature, which is 20 bytes of r, | |
| 254 ** followed by 20 bytes of s. | |
| 255 */ | |
| 256 SECItem * | |
| 257 DSAU_DecodeDerSig(const SECItem *item) | |
| 258 { | |
| 259 return common_DecodeDerSig(item, DSA1_SUBPRIME_LEN); | |
| 260 } | |
| 261 | |
| 262 /* src is a DER-encoded ECDSA signature. | |
| 263 ** Returns a newly-allocated SECItem structure, pointing at a newly allocated | |
| 264 ** buffer containing the "raw" ECDSA signature of length len containing | |
| 265 ** r followed by s (both padded to take up exactly len/2 bytes). | |
| 266 */ | |
| 267 SECItem * | |
| 268 DSAU_DecodeDerSigToLen(const SECItem *item, unsigned int len) | |
| 269 { | |
| 270 return common_DecodeDerSig(item, len / 2); | |
| 271 } | |
| OLD | NEW |