1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/cryptohi/dsautil.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,267 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +#include "cryptohi.h" 1.8 +#include "secasn1.h" 1.9 +#include "secitem.h" 1.10 +#include "prerr.h" 1.11 + 1.12 +#ifndef DSA1_SUBPRIME_LEN 1.13 +#define DSA1_SUBPRIME_LEN 20 /* bytes */ 1.14 +#endif 1.15 + 1.16 +typedef struct { 1.17 + SECItem r; 1.18 + SECItem s; 1.19 +} DSA_ASN1Signature; 1.20 + 1.21 +const SEC_ASN1Template DSA_SignatureTemplate[] = 1.22 +{ 1.23 + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(DSA_ASN1Signature) }, 1.24 + { SEC_ASN1_INTEGER, offsetof(DSA_ASN1Signature,r) }, 1.25 + { SEC_ASN1_INTEGER, offsetof(DSA_ASN1Signature,s) }, 1.26 + { 0, } 1.27 +}; 1.28 + 1.29 +/* Input is variable length multi-byte integer, MSB first (big endian). 1.30 +** Most signficant bit of first byte is NOT treated as a sign bit. 1.31 +** May be one or more leading bytes of zeros. 1.32 +** Output is variable length multi-byte integer, MSB first (big endian). 1.33 +** Most significant bit of first byte will be zero (positive sign bit) 1.34 +** No more than one leading zero byte. 1.35 +** Caller supplies dest buffer, and assures that it is long enough, 1.36 +** e.g. at least one byte longer that src's buffer. 1.37 +*/ 1.38 +void 1.39 +DSAU_ConvertUnsignedToSigned(SECItem *dest, SECItem *src) 1.40 +{ 1.41 + unsigned char *pSrc = src->data; 1.42 + unsigned char *pDst = dest->data; 1.43 + unsigned int cntSrc = src->len; 1.44 + 1.45 + /* skip any leading zeros. */ 1.46 + while (cntSrc && !(*pSrc)) { 1.47 + pSrc++; 1.48 + cntSrc--; 1.49 + } 1.50 + if (!cntSrc) { 1.51 + *pDst = 0; 1.52 + dest->len = 1; 1.53 + return; 1.54 + } 1.55 + 1.56 + if (*pSrc & 0x80) 1.57 + *pDst++ = 0; 1.58 + 1.59 + PORT_Memcpy(pDst, pSrc, cntSrc); 1.60 + dest->len = (pDst - dest->data) + cntSrc; 1.61 +} 1.62 + 1.63 +/* 1.64 +** src is a buffer holding a signed variable length integer. 1.65 +** dest is a buffer which will be filled with an unsigned integer, 1.66 +** MSB first (big endian) with leading zeros, so that the last byte 1.67 +** of src will be the LSB of the integer. The result will be exactly 1.68 +** the length specified by the caller in dest->len. 1.69 +** src can be shorter than dest. src can be longer than dst, but only 1.70 +** if the extra leading bytes are zeros. 1.71 +*/ 1.72 +SECStatus 1.73 +DSAU_ConvertSignedToFixedUnsigned(SECItem *dest, SECItem *src) 1.74 +{ 1.75 + unsigned char *pSrc = src->data; 1.76 + unsigned char *pDst = dest->data; 1.77 + unsigned int cntSrc = src->len; 1.78 + unsigned int cntDst = dest->len; 1.79 + int zCount = cntDst - cntSrc; 1.80 + 1.81 + if (zCount > 0) { 1.82 + PORT_Memset(pDst, 0, zCount); 1.83 + PORT_Memcpy(pDst + zCount, pSrc, cntSrc); 1.84 + return SECSuccess; 1.85 + } 1.86 + if (zCount <= 0) { 1.87 + /* Source is longer than destination. Check for leading zeros. */ 1.88 + while (zCount++ < 0) { 1.89 + if (*pSrc++ != 0) 1.90 + goto loser; 1.91 + } 1.92 + } 1.93 + PORT_Memcpy(pDst, pSrc, cntDst); 1.94 + return SECSuccess; 1.95 + 1.96 +loser: 1.97 + PORT_SetError( PR_INVALID_ARGUMENT_ERROR ); 1.98 + return SECFailure; 1.99 +} 1.100 + 1.101 +/* src is a "raw" ECDSA or DSA signature, the first half contains r 1.102 + * and the second half contains s. dest is the DER encoded signature. 1.103 +*/ 1.104 +static SECStatus 1.105 +common_EncodeDerSig(SECItem *dest, SECItem *src) 1.106 +{ 1.107 + SECItem * item; 1.108 + SECItem srcItem; 1.109 + DSA_ASN1Signature sig; 1.110 + unsigned char *signedR; 1.111 + unsigned char *signedS; 1.112 + unsigned int len; 1.113 + 1.114 + /* Allocate memory with room for an extra byte that 1.115 + * may be required if the top bit in the first byte 1.116 + * is already set. 1.117 + */ 1.118 + len = src->len/2; 1.119 + signedR = (unsigned char *) PORT_Alloc(len + 1); 1.120 + if (!signedR) return SECFailure; 1.121 + signedS = (unsigned char *) PORT_ZAlloc(len + 1); 1.122 + if (!signedS) { 1.123 + if (signedR) PORT_Free(signedR); 1.124 + return SECFailure; 1.125 + } 1.126 + 1.127 + PORT_Memset(&sig, 0, sizeof(sig)); 1.128 + 1.129 + /* Must convert r and s from "unsigned" integers to "signed" integers. 1.130 + ** If the high order bit of the first byte (MSB) is 1, then must 1.131 + ** prepend with leading zero. 1.132 + ** Must remove all but one leading zero byte from numbers. 1.133 + */ 1.134 + sig.r.type = siUnsignedInteger; 1.135 + sig.r.data = signedR; 1.136 + sig.r.len = sizeof signedR; 1.137 + sig.s.type = siUnsignedInteger; 1.138 + sig.s.data = signedS; 1.139 + sig.s.len = sizeof signedR; 1.140 + 1.141 + srcItem.data = src->data; 1.142 + srcItem.len = len; 1.143 + 1.144 + DSAU_ConvertUnsignedToSigned(&sig.r, &srcItem); 1.145 + srcItem.data += len; 1.146 + DSAU_ConvertUnsignedToSigned(&sig.s, &srcItem); 1.147 + 1.148 + item = SEC_ASN1EncodeItem(NULL, dest, &sig, DSA_SignatureTemplate); 1.149 + if (signedR) PORT_Free(signedR); 1.150 + if (signedS) PORT_Free(signedS); 1.151 + if (item == NULL) 1.152 + return SECFailure; 1.153 + 1.154 + /* XXX leak item? */ 1.155 + return SECSuccess; 1.156 +} 1.157 + 1.158 +/* src is a DER-encoded ECDSA or DSA signature. 1.159 +** Returns a newly-allocated SECItem structure, pointing at a newly allocated 1.160 +** buffer containing the "raw" signature, which is len bytes of r, 1.161 +** followed by len bytes of s. For DSA, len is the length of q. 1.162 +** For ECDSA, len depends on the key size used to create the signature. 1.163 +*/ 1.164 +static SECItem * 1.165 +common_DecodeDerSig(const SECItem *item, unsigned int len) 1.166 +{ 1.167 + SECItem * result = NULL; 1.168 + SECStatus status; 1.169 + DSA_ASN1Signature sig; 1.170 + SECItem dst; 1.171 + 1.172 + PORT_Memset(&sig, 0, sizeof(sig)); 1.173 + 1.174 + result = PORT_ZNew(SECItem); 1.175 + if (result == NULL) 1.176 + goto loser; 1.177 + 1.178 + result->len = 2 * len; 1.179 + result->data = (unsigned char*)PORT_Alloc(2 * len); 1.180 + if (result->data == NULL) 1.181 + goto loser; 1.182 + 1.183 + sig.r.type = siUnsignedInteger; 1.184 + sig.s.type = siUnsignedInteger; 1.185 + status = SEC_ASN1DecodeItem(NULL, &sig, DSA_SignatureTemplate, item); 1.186 + if (status != SECSuccess) 1.187 + goto loser; 1.188 + 1.189 + /* Convert sig.r and sig.s from variable length signed integers to 1.190 + ** fixed length unsigned integers. 1.191 + */ 1.192 + dst.data = result->data; 1.193 + dst.len = len; 1.194 + status = DSAU_ConvertSignedToFixedUnsigned(&dst, &sig.r); 1.195 + if (status != SECSuccess) 1.196 + goto loser; 1.197 + 1.198 + dst.data += len; 1.199 + status = DSAU_ConvertSignedToFixedUnsigned(&dst, &sig.s); 1.200 + if (status != SECSuccess) 1.201 + goto loser; 1.202 + 1.203 +done: 1.204 + if (sig.r.data != NULL) 1.205 + PORT_Free(sig.r.data); 1.206 + if (sig.s.data != NULL) 1.207 + PORT_Free(sig.s.data); 1.208 + 1.209 + return result; 1.210 + 1.211 +loser: 1.212 + if (result != NULL) { 1.213 + SECITEM_FreeItem(result, PR_TRUE); 1.214 + result = NULL; 1.215 + } 1.216 + goto done; 1.217 +} 1.218 + 1.219 +/* src is a "raw" DSA1 signature, 20 bytes of r followed by 20 bytes of s. 1.220 +** dest is the signature DER encoded. ? 1.221 +*/ 1.222 +SECStatus 1.223 +DSAU_EncodeDerSig(SECItem *dest, SECItem *src) 1.224 +{ 1.225 + PORT_Assert(src->len == 2 * DSA1_SUBPRIME_LEN); 1.226 + if (src->len != 2 * DSA1_SUBPRIME_LEN) { 1.227 + PORT_SetError( PR_INVALID_ARGUMENT_ERROR ); 1.228 + return SECFailure; 1.229 + } 1.230 + 1.231 + return common_EncodeDerSig(dest, src); 1.232 +} 1.233 + 1.234 +/* src is a "raw" DSA signature of length len (len/2 bytes of r followed 1.235 +** by len/2 bytes of s). dest is the signature DER encoded. 1.236 +*/ 1.237 +SECStatus 1.238 +DSAU_EncodeDerSigWithLen(SECItem *dest, SECItem *src, unsigned int len) 1.239 +{ 1.240 + 1.241 + PORT_Assert((src->len == len) && (len % 2 == 0)); 1.242 + if ((src->len != len) || (src->len % 2 != 0)) { 1.243 + PORT_SetError( PR_INVALID_ARGUMENT_ERROR ); 1.244 + return SECFailure; 1.245 + } 1.246 + 1.247 + return common_EncodeDerSig(dest, src); 1.248 +} 1.249 + 1.250 +/* src is a DER-encoded DSA signature. 1.251 +** Returns a newly-allocated SECItem structure, pointing at a newly allocated 1.252 +** buffer containing the "raw" DSA1 signature, which is 20 bytes of r, 1.253 +** followed by 20 bytes of s. 1.254 +*/ 1.255 +SECItem * 1.256 +DSAU_DecodeDerSig(const SECItem *item) 1.257 +{ 1.258 + return common_DecodeDerSig(item, DSA1_SUBPRIME_LEN); 1.259 +} 1.260 + 1.261 +/* src is a DER-encoded ECDSA signature. 1.262 +** Returns a newly-allocated SECItem structure, pointing at a newly allocated 1.263 +** buffer containing the "raw" ECDSA signature of length len containing 1.264 +** r followed by s (both padded to take up exactly len/2 bytes). 1.265 +*/ 1.266 +SECItem * 1.267 +DSAU_DecodeDerSigToLen(const SECItem *item, unsigned int len) 1.268 +{ 1.269 + return common_DecodeDerSig(item, len/2); 1.270 +}