security/nss/lib/cryptohi/dsautil.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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"
     9 #ifndef DSA1_SUBPRIME_LEN
    10 #define DSA1_SUBPRIME_LEN 20	/* bytes */
    11 #endif
    13 typedef struct {
    14     SECItem r;
    15     SECItem s;
    16 } DSA_ASN1Signature;
    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 };
    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;
    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     }
    53     if (*pSrc & 0x80)
    54     	*pDst++ = 0;
    56     PORT_Memcpy(pDst, pSrc, cntSrc);
    57     dest->len = (pDst - dest->data) + cntSrc;
    58 }
    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;
    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;
    93 loser:
    94     PORT_SetError( PR_INVALID_ARGUMENT_ERROR );
    95     return SECFailure;
    96 }
    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;
   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     }
   124     PORT_Memset(&sig, 0, sizeof(sig));
   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;
   138     srcItem.data = src->data;
   139     srcItem.len  = len;
   141     DSAU_ConvertUnsignedToSigned(&sig.r, &srcItem);
   142     srcItem.data += len;
   143     DSAU_ConvertUnsignedToSigned(&sig.s, &srcItem);
   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;
   151     /* XXX leak item? */
   152     return SECSuccess;
   153 }
   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;
   169     PORT_Memset(&sig, 0, sizeof(sig));
   171     result = PORT_ZNew(SECItem);
   172     if (result == NULL)
   173 	goto loser;
   175     result->len  = 2 * len;
   176     result->data = (unsigned char*)PORT_Alloc(2 * len);
   177     if (result->data == NULL)
   178 	goto loser;
   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;
   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;
   195     dst.data += len;
   196     status = DSAU_ConvertSignedToFixedUnsigned(&dst, &sig.s);
   197     if (status != SECSuccess)
   198     	goto loser;
   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);
   206     return result;
   208 loser:
   209     if (result != NULL) {
   210 	SECITEM_FreeItem(result, PR_TRUE);
   211 	result = NULL;
   212     }
   213     goto done;
   214 }
   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     }
   228     return common_EncodeDerSig(dest, src);
   229 }
   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 {
   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     }
   244     return common_EncodeDerSig(dest, src);
   245 }
   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 }
   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 }

mercurial