| 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) return SECFailure; | |
| 118 signedS = (unsigned char *) PORT_ZAlloc(len + 1); | |
| 119 if (!signedS) { | |
| 120 if (signedR) PORT_Free(signedR); | |
| 121 return SECFailure; | |
| 122 } | |
| 123 | |
| 124 PORT_Memset(&sig, 0, sizeof(sig)); | |
| 125 | |
| 126 /* Must convert r and s from "unsigned" integers to "signed" integers. | |
| 127 ** If the high order bit of the first byte (MSB) is 1, then must | |
| 128 ** prepend with leading zero. | |
| 129 ** Must remove all but one leading zero byte from numbers. | |
| 130 */ | |
| 131 sig.r.type = siUnsignedInteger; | |
| 132 sig.r.data = signedR; | |
| 133 sig.r.len = sizeof signedR; | |
| 134 sig.s.type = siUnsignedInteger; | |
| 135 sig.s.data = signedS; | |
| 136 sig.s.len = sizeof signedR; | |
| 137 | |
| 138 srcItem.data = src->data; | |
| 139 srcItem.len = len; | |
| 140 | |
| 141 DSAU_ConvertUnsignedToSigned(&sig.r, &srcItem); | |
| 142 srcItem.data += len; | |
| 143 DSAU_ConvertUnsignedToSigned(&sig.s, &srcItem); | |
| 144 | |
| 145 item = SEC_ASN1EncodeItem(NULL, dest, &sig, DSA_SignatureTemplate); | |
| 146 if (signedR) PORT_Free(signedR); | |
| 147 if (signedS) PORT_Free(signedS); | |
| 148 if (item == NULL) | |
| 149 return SECFailure; | |
| 150 | |
| 151 /* XXX leak item? */ | |
| 152 return SECSuccess; | |
| 153 } | |
| 154 | |
| 155 /* src is a DER-encoded ECDSA or DSA signature. | |
| 156 ** Returns a newly-allocated SECItem structure, pointing at a newly allocated | |
| 157 ** buffer containing the "raw" signature, which is len bytes of r, | |
| 158 ** followed by len bytes of s. For DSA, len is the length of q. | |
| 159 ** For ECDSA, len depends on the key size used to create the signature. | |
| 160 */ | |
| 161 static SECItem * | |
| 162 common_DecodeDerSig(const SECItem *item, unsigned int len) | |
| 163 { | |
| 164 SECItem * result = NULL; | |
| 165 SECStatus status; | |
| 166 DSA_ASN1Signature sig; | |
| 167 SECItem dst; | |
| 168 | |
| 169 PORT_Memset(&sig, 0, sizeof(sig)); | |
| 170 | |
| 171 result = PORT_ZNew(SECItem); | |
| 172 if (result == NULL) | |
| 173 goto loser; | |
| 174 | |
| 175 result->len = 2 * len; | |
| 176 result->data = (unsigned char*)PORT_Alloc(2 * len); | |
| 177 if (result->data == NULL) | |
| 178 goto loser; | |
| 179 | |
| 180 sig.r.type = siUnsignedInteger; | |
| 181 sig.s.type = siUnsignedInteger; | |
| 182 status = SEC_ASN1DecodeItem(NULL, &sig, DSA_SignatureTemplate, item); | |
| 183 if (status != SECSuccess) | |
| 184 goto loser; | |
| 185 | |
| 186 /* Convert sig.r and sig.s from variable length signed integers to | |
| 187 ** fixed length unsigned integers. | |
| 188 */ | |
| 189 dst.data = result->data; | |
| 190 dst.len = len; | |
| 191 status = DSAU_ConvertSignedToFixedUnsigned(&dst, &sig.r); | |
| 192 if (status != SECSuccess) | |
| 193 goto loser; | |
| 194 | |
| 195 dst.data += len; | |
| 196 status = DSAU_ConvertSignedToFixedUnsigned(&dst, &sig.s); | |
| 197 if (status != SECSuccess) | |
| 198 goto loser; | |
| 199 | |
| 200 done: | |
| 201 if (sig.r.data != NULL) | |
| 202 PORT_Free(sig.r.data); | |
| 203 if (sig.s.data != NULL) | |
| 204 PORT_Free(sig.s.data); | |
| 205 | |
| 206 return result; | |
| 207 | |
| 208 loser: | |
| 209 if (result != NULL) { | |
| 210 SECITEM_FreeItem(result, PR_TRUE); | |
| 211 result = NULL; | |
| 212 } | |
| 213 goto done; | |
| 214 } | |
| 215 | |
| 216 /* src is a "raw" DSA1 signature, 20 bytes of r followed by 20 bytes of s. | |
| 217 ** dest is the signature DER encoded. ? | |
| 218 */ | |
| 219 SECStatus | |
| 220 DSAU_EncodeDerSig(SECItem *dest, SECItem *src) | |
| 221 { | |
| 222 PORT_Assert(src->len == 2 * DSA1_SUBPRIME_LEN); | |
| 223 if (src->len != 2 * DSA1_SUBPRIME_LEN) { | |
| 224 PORT_SetError( PR_INVALID_ARGUMENT_ERROR ); | |
| 225 return SECFailure; | |
| 226 } | |
| 227 | |
| 228 return common_EncodeDerSig(dest, src); | |
| 229 } | |
| 230 | |
| 231 /* src is a "raw" DSA signature of length len (len/2 bytes of r followed | |
| 232 ** by len/2 bytes of s). dest is the signature DER encoded. | |
| 233 */ | |
| 234 SECStatus | |
| 235 DSAU_EncodeDerSigWithLen(SECItem *dest, SECItem *src, unsigned int len) | |
| 236 { | |
| 237 | |
| 238 PORT_Assert((src->len == len) && (len % 2 == 0)); | |
| 239 if ((src->len != len) || (src->len % 2 != 0)) { | |
| 240 PORT_SetError( PR_INVALID_ARGUMENT_ERROR ); | |
| 241 return SECFailure; | |
| 242 } | |
| 243 | |
| 244 return common_EncodeDerSig(dest, src); | |
| 245 } | |
| 246 | |
| 247 /* src is a DER-encoded DSA signature. | |
| 248 ** Returns a newly-allocated SECItem structure, pointing at a newly allocated | |
| 249 ** buffer containing the "raw" DSA1 signature, which is 20 bytes of r, | |
| 250 ** followed by 20 bytes of s. | |
| 251 */ | |
| 252 SECItem * | |
| 253 DSAU_DecodeDerSig(const SECItem *item) | |
| 254 { | |
| 255 return common_DecodeDerSig(item, DSA1_SUBPRIME_LEN); | |
| 256 } | |
| 257 | |
| 258 /* src is a DER-encoded ECDSA signature. | |
| 259 ** Returns a newly-allocated SECItem structure, pointing at a newly allocated | |
| 260 ** buffer containing the "raw" ECDSA signature of length len containing | |
| 261 ** r followed by s (both padded to take up exactly len/2 bytes). | |
| 262 */ | |
| 263 SECItem * | |
| 264 DSAU_DecodeDerSigToLen(const SECItem *item, unsigned int len) | |
| 265 { | |
| 266 return common_DecodeDerSig(item, len/2); | |
| 267 } | |
| OLD | NEW |