|
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 } |