From a29542b7fa6c4b40e485e023b364432308bd5a64 Mon Sep 17 00:00:00 2001 From: "ian.mcgreer%sun.com" Date: Mon, 14 Jan 2002 23:20:43 +0000 Subject: [PATCH] fix for bug 115360, ASN.1 encoder/decoder should handle conversion of unsigned integers used in NSS to ASN.1 INTEGERs, and vice versa. --- security/nss/lib/pk11wrap/pk11skey.c | 21 +++++++------------ security/nss/lib/softoken/pkcs11u.c | 23 +++++---------------- security/nss/lib/util/secasn1d.c | 18 +++++++++++++--- security/nss/lib/util/secasn1e.c | 31 +++++++++++++++++++++++++++- 4 files changed, 58 insertions(+), 35 deletions(-) diff --git a/security/nss/lib/pk11wrap/pk11skey.c b/security/nss/lib/pk11wrap/pk11skey.c index ae1505aa1b65..b66649924810 100644 --- a/security/nss/lib/pk11wrap/pk11skey.c +++ b/security/nss/lib/pk11wrap/pk11skey.c @@ -634,26 +634,21 @@ PK11_GetKeyData(PK11SymKey *symKey) } /* - * take an attribute and copy it into a secitem, converting unsigned to signed. + * take an attribute and copy it into a secitem */ static CK_RV -pk11_Attr2SecItem(PRArenaPool *arena, CK_ATTRIBUTE *attr, SECItem *item) { - unsigned char *dataPtr; +pk11_Attr2SecItem(PRArenaPool *arena, CK_ATTRIBUTE *attr, SECItem *item) +{ + item->data = NULL; - item->len = attr->ulValueLen; - dataPtr = (unsigned char*) PORT_ArenaAlloc(arena, item->len+1); - if ( dataPtr == NULL) { + (void)SECITEM_AllocItem(arena, item, attr->ulValueLen); + if (item->data == NULL) { return CKR_HOST_MEMORY; } - *dataPtr = 0; - item->data = dataPtr+1; - PORT_Memcpy(item->data,attr->pValue,item->len); - if (item->data[0] & 0x80) { - item->data = item->data-1; - item->len++; - } + PORT_Memcpy(item->data, attr->pValue, item->len); return CKR_OK; } + /* * extract a public key from a slot and id */ diff --git a/security/nss/lib/softoken/pkcs11u.c b/security/nss/lib/softoken/pkcs11u.c index c7909d2a9e9a..127d910d7137 100644 --- a/security/nss/lib/softoken/pkcs11u.c +++ b/security/nss/lib/softoken/pkcs11u.c @@ -1165,40 +1165,27 @@ pk11_AddAttribute(PK11Object *object,PK11Attribute *attribute) } /* - * copy an unsigned attribute into a 'signed' SECItem. Secitem is allocated in + * copy an unsigned attribute into a SECItem. Secitem is allocated in * the specified arena. */ CK_RV pk11_Attribute2SSecItem(PLArenaPool *arena,SECItem *item,PK11Object *object, CK_ATTRIBUTE_TYPE type) { - int len; PK11Attribute *attribute; unsigned char *start; - int real_len; + + item->data = NULL; attribute = pk11_FindAttribute(object, type); if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE; - real_len = len = attribute->attrib.ulValueLen; - if ((*((unsigned char *)attribute->attrib.pValue) & 0x80) != 0) { - real_len++; - } - if (arena) { - start = item->data = (unsigned char *) PORT_ArenaAlloc(arena,real_len); - } else { - start = item->data = (unsigned char *) PORT_Alloc(real_len); - } + (void)SECITEM_AllocItem(arena, item, attribute->attrib.ulValueLen); if (item->data == NULL) { pk11_FreeAttribute(attribute); return CKR_HOST_MEMORY; } - item->len = real_len; - if (real_len != len) { - *start = 0; - start++; - } - PORT_Memcpy(start, attribute->attrib.pValue, len); + PORT_Memcpy(item->data, attribute->attrib.pValue, item->len); pk11_FreeAttribute(attribute); return CKR_OK; } diff --git a/security/nss/lib/util/secasn1d.c b/security/nss/lib/util/secasn1d.c index ac2b249217b7..f705d3db1428 100644 --- a/security/nss/lib/util/secasn1d.c +++ b/security/nss/lib/util/secasn1d.c @@ -35,7 +35,7 @@ * Support for DEcoding ASN.1 data based on BER/DER (Basic/Distinguished * Encoding Rules). * - * $Id: secasn1d.c,v 1.13 2002/01/11 00:33:08 relyea%netscape.com Exp $ + * $Id: secasn1d.c,v 1.14 2002/01/14 23:20:42 ian.mcgreer%sun.com Exp $ */ #include "secasn1.h" @@ -1324,6 +1324,7 @@ sec_asn1d_parse_leaf (sec_asn1d_state *state, const char *buf, unsigned long len) { SECItem *item; + unsigned long bufLen; if (len == 0) { state->top->status = needBytes; @@ -1333,16 +1334,27 @@ sec_asn1d_parse_leaf (sec_asn1d_state *state, if (state->pending < len) len = state->pending; + bufLen = len; + item = (SECItem *)(state->dest); if (item != NULL && item->data != NULL) { + /* Strip leading zeroes */ + if (state->underlying_kind == SEC_ASN1_INTEGER && /* INTEGER */ + item->len == 0) /* MSB */ + { + while (len > 1 && buf[0] == 0) { /* leading 0 */ + buf++; + len--; + } + } PORT_Memcpy (item->data + item->len, buf, len); item->len += len; } - state->pending -= len; + state->pending -= bufLen; if (state->pending == 0) state->place = beforeEndOfContents; - return len; + return bufLen; } diff --git a/security/nss/lib/util/secasn1e.c b/security/nss/lib/util/secasn1e.c index 1aca1cf09277..999a23cddac3 100644 --- a/security/nss/lib/util/secasn1e.c +++ b/security/nss/lib/util/secasn1e.c @@ -35,7 +35,7 @@ * Support for ENcoding ASN.1 data based on BER/DER (Basic/Distinguished * Encoding Rules). * - * $Id: secasn1e.c,v 1.4 2001/08/03 00:37:53 javi%netscape.com Exp $ + * $Id: secasn1e.c,v 1.5 2002/01/14 23:20:43 ian.mcgreer%sun.com Exp $ */ #include "secasn1.h" @@ -684,6 +684,17 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src, len++; break; + case SEC_ASN1_INTEGER: + /* ASN.1 INTEGERs are signed. PKCS#11 BigIntegers are unsigned. NSS + * will treat numbers going in and out of the ASN.1 encoder as + * unsigned, so the encoder must handle the conversion. + */ + len = ((SECItem *)src)->len; + if (len > 0 && ((SECItem *)src)->data[0] & 0x80) { + len++; /* will add leading 0 */ + } + break; + default: len = ((SECItem *)src)->len; if (may_stream && len == 0 && !ignoresubstream) @@ -977,6 +988,24 @@ sec_asn1e_write_contents (sec_asn1e_state *state, } /* otherwise, fall through to write the content */ goto process_string; + + case SEC_ASN1_INTEGER: + /* ASN.1 INTEGERs are signed. PKCS#11 BigIntegers are unsigned. + * NSS will treat numbers going in and out of the ASN.1 encoder as + * unsigned, so the encoder must handle the conversion. + */ + { + SECItem *item; + + item = (SECItem *)state->src; + if (item->len > 0 && item->data[0] & 0x80) + { + char zero = 0; /* write a leading 0 */ + sec_asn1e_write_contents_bytes (state, &zero, 1); + } + } + /* fall through to write the content */ + goto process_string; process_string: default: