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 |