Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / cryptohi / dsautil.c
blob231a793b4312e161cf9d76ac20843bf5a4388cd6
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
37 #include "cryptohi.h"
38 #include "secasn1.h"
39 #include "secitem.h"
40 #include "prerr.h"
42 #ifndef DSA_SUBPRIME_LEN
43 #define DSA_SUBPRIME_LEN 20 /* bytes */
44 #endif
46 typedef struct {
47 SECItem r;
48 SECItem s;
49 } DSA_ASN1Signature;
51 const SEC_ASN1Template DSA_SignatureTemplate[] =
53 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(DSA_ASN1Signature) },
54 { SEC_ASN1_INTEGER, offsetof(DSA_ASN1Signature,r) },
55 { SEC_ASN1_INTEGER, offsetof(DSA_ASN1Signature,s) },
56 { 0, }
59 /* Input is variable length multi-byte integer, MSB first (big endian).
60 ** Most signficant bit of first byte is NOT treated as a sign bit.
61 ** May be one or more leading bytes of zeros.
62 ** Output is variable length multi-byte integer, MSB first (big endian).
63 ** Most significant bit of first byte will be zero (positive sign bit)
64 ** No more than one leading zero byte.
65 ** Caller supplies dest buffer, and assures that it is long enough,
66 ** e.g. at least one byte longer that src's buffer.
68 void
69 DSAU_ConvertUnsignedToSigned(SECItem *dest, SECItem *src)
71 unsigned char *pSrc = src->data;
72 unsigned char *pDst = dest->data;
73 unsigned int cntSrc = src->len;
75 /* skip any leading zeros. */
76 while (cntSrc && !(*pSrc)) {
77 pSrc++;
78 cntSrc--;
80 if (!cntSrc) {
81 *pDst = 0;
82 dest->len = 1;
83 return;
86 if (*pSrc & 0x80)
87 *pDst++ = 0;
89 PORT_Memcpy(pDst, pSrc, cntSrc);
90 dest->len = (pDst - dest->data) + cntSrc;
94 ** src is a buffer holding a signed variable length integer.
95 ** dest is a buffer which will be filled with an unsigned integer,
96 ** MSB first (big endian) with leading zeros, so that the last byte
97 ** of src will be the LSB of the integer. The result will be exactly
98 ** the length specified by the caller in dest->len.
99 ** src can be shorter than dest. src can be longer than dst, but only
100 ** if the extra leading bytes are zeros.
102 SECStatus
103 DSAU_ConvertSignedToFixedUnsigned(SECItem *dest, SECItem *src)
105 unsigned char *pSrc = src->data;
106 unsigned char *pDst = dest->data;
107 unsigned int cntSrc = src->len;
108 unsigned int cntDst = dest->len;
109 int zCount = cntDst - cntSrc;
111 if (zCount > 0) {
112 PORT_Memset(pDst, 0, zCount);
113 PORT_Memcpy(pDst + zCount, pSrc, cntSrc);
114 return SECSuccess;
116 if (zCount <= 0) {
117 /* Source is longer than destination. Check for leading zeros. */
118 while (zCount++ < 0) {
119 if (*pSrc++ != 0)
120 goto loser;
123 PORT_Memcpy(pDst, pSrc, cntDst);
124 return SECSuccess;
126 loser:
127 PORT_SetError( PR_INVALID_ARGUMENT_ERROR );
128 return SECFailure;
131 /* src is a "raw" ECDSA or DSA signature, the first half contains r
132 * and the second half contains s. dest is the DER encoded signature.
134 static SECStatus
135 common_EncodeDerSig(SECItem *dest, SECItem *src)
137 SECItem * item;
138 SECItem srcItem;
139 DSA_ASN1Signature sig;
140 unsigned char *signedR;
141 unsigned char *signedS;
142 unsigned int len;
144 /* Allocate memory with room for an extra byte that
145 * may be required if the top bit in the first byte
146 * is already set.
148 len = src->len/2;
149 signedR = (unsigned char *) PORT_Alloc(len + 1);
150 if (!signedR) return SECFailure;
151 signedS = (unsigned char *) PORT_ZAlloc(len + 1);
152 if (!signedS) {
153 if (signedR) PORT_Free(signedR);
154 return SECFailure;
157 PORT_Memset(&sig, 0, sizeof(sig));
159 /* Must convert r and s from "unsigned" integers to "signed" integers.
160 ** If the high order bit of the first byte (MSB) is 1, then must
161 ** prepend with leading zero.
162 ** Must remove all but one leading zero byte from numbers.
164 sig.r.type = siUnsignedInteger;
165 sig.r.data = signedR;
166 sig.r.len = sizeof signedR;
167 sig.s.type = siUnsignedInteger;
168 sig.s.data = signedS;
169 sig.s.len = sizeof signedR;
171 srcItem.data = src->data;
172 srcItem.len = len;
174 DSAU_ConvertUnsignedToSigned(&sig.r, &srcItem);
175 srcItem.data += len;
176 DSAU_ConvertUnsignedToSigned(&sig.s, &srcItem);
178 item = SEC_ASN1EncodeItem(NULL, dest, &sig, DSA_SignatureTemplate);
179 if (signedR) PORT_Free(signedR);
180 if (signedS) PORT_Free(signedS);
181 if (item == NULL)
182 return SECFailure;
184 /* XXX leak item? */
185 return SECSuccess;
188 /* src is a DER-encoded ECDSA or DSA signature.
189 ** Returns a newly-allocated SECItem structure, pointing at a newly allocated
190 ** buffer containing the "raw" signature, which is len bytes of r,
191 ** followed by len bytes of s. For DSA, len is always DSA_SUBPRIME_LEN.
192 ** For ECDSA, len depends on the key size used to create the signature.
194 static SECItem *
195 common_DecodeDerSig(const SECItem *item, unsigned int len)
197 SECItem * result = NULL;
198 SECStatus status;
199 DSA_ASN1Signature sig;
200 SECItem dst;
202 PORT_Memset(&sig, 0, sizeof(sig));
204 result = PORT_ZNew(SECItem);
205 if (result == NULL)
206 goto loser;
208 result->len = 2 * len;
209 result->data = (unsigned char*)PORT_Alloc(2 * len);
210 if (result->data == NULL)
211 goto loser;
213 sig.r.type = siUnsignedInteger;
214 sig.s.type = siUnsignedInteger;
215 status = SEC_ASN1DecodeItem(NULL, &sig, DSA_SignatureTemplate, item);
216 if (status != SECSuccess)
217 goto loser;
219 /* Convert sig.r and sig.s from variable length signed integers to
220 ** fixed length unsigned integers.
222 dst.data = result->data;
223 dst.len = len;
224 status = DSAU_ConvertSignedToFixedUnsigned(&dst, &sig.r);
225 if (status != SECSuccess)
226 goto loser;
228 dst.data += len;
229 status = DSAU_ConvertSignedToFixedUnsigned(&dst, &sig.s);
230 if (status != SECSuccess)
231 goto loser;
233 done:
234 if (sig.r.data != NULL)
235 PORT_Free(sig.r.data);
236 if (sig.s.data != NULL)
237 PORT_Free(sig.s.data);
239 return result;
241 loser:
242 if (result != NULL) {
243 SECITEM_FreeItem(result, PR_TRUE);
244 result = NULL;
246 goto done;
249 /* src is a "raw" DSA signature, 20 bytes of r followed by 20 bytes of s.
250 ** dest is the signature DER encoded. ?
252 SECStatus
253 DSAU_EncodeDerSig(SECItem *dest, SECItem *src)
255 PORT_Assert(src->len == 2 * DSA_SUBPRIME_LEN);
256 if (src->len != 2 * DSA_SUBPRIME_LEN) {
257 PORT_SetError( PR_INVALID_ARGUMENT_ERROR );
258 return SECFailure;
261 return common_EncodeDerSig(dest, src);
264 /* src is a "raw" DSA signature of length len (len/2 bytes of r followed
265 ** by len/2 bytes of s). dest is the signature DER encoded.
267 SECStatus
268 DSAU_EncodeDerSigWithLen(SECItem *dest, SECItem *src, unsigned int len)
271 PORT_Assert((src->len == len) && (len % 2 == 0));
272 if ((src->len != len) || (src->len % 2 != 0)) {
273 PORT_SetError( PR_INVALID_ARGUMENT_ERROR );
274 return SECFailure;
277 return common_EncodeDerSig(dest, src);
280 /* src is a DER-encoded DSA signature.
281 ** Returns a newly-allocated SECItem structure, pointing at a newly allocated
282 ** buffer containing the "raw" DSA signature, which is 20 bytes of r,
283 ** followed by 20 bytes of s.
285 SECItem *
286 DSAU_DecodeDerSig(const SECItem *item)
288 return common_DecodeDerSig(item, DSA_SUBPRIME_LEN);
291 /* src is a DER-encoded ECDSA signature.
292 ** Returns a newly-allocated SECItem structure, pointing at a newly allocated
293 ** buffer containing the "raw" ECDSA signature of length len containing
294 ** r followed by s (both padded to take up exactly len/2 bytes).
296 SECItem *
297 DSAU_DecodeDerSigToLen(const SECItem *item, unsigned int len)
299 return common_DecodeDerSig(item, len/2);