Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/cryptohi/dsautil.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
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 } |