diff options
Diffstat (limited to 'security/nss/lib')
192 files changed, 39490 insertions, 7678 deletions
diff --git a/security/nss/lib/certdb/certdb.c b/security/nss/lib/certdb/certdb.c index d7742d83c..9c5c22f31 100644 --- a/security/nss/lib/certdb/certdb.c +++ b/security/nss/lib/certdb/certdb.c @@ -545,6 +545,7 @@ cert_GetCertType(CERTCertificate *cert) tmpitem.data = NULL; CERT_FindNSCertTypeExtension(cert, &tmpitem); + encodedExtKeyUsage.data = NULL; rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &encodedExtKeyUsage); if (rv == SECSuccess) { @@ -671,8 +672,10 @@ cert_GetCertType(CERTCertificate *cert) } } - if (extKeyUsage != NULL) { + if (encodedExtKeyUsage.data != NULL) { PORT_Free(encodedExtKeyUsage.data); + } + if (extKeyUsage != NULL) { CERT_DestroyOidSequence(extKeyUsage); } /* Assert that it is safe to cast &cert->nsCertType to "PRInt32 *" */ @@ -1910,6 +1913,45 @@ CERT_IsRootDERCert(SECItem *derCert) return isRoot; } +CERTCompareValidityStatus +CERT_CompareValidityTimes(CERTValidity* val_a, CERTValidity* val_b) +{ + PRTime notBeforeA, notBeforeB, notAfterA, notAfterB; + + if (!val_a || !val_b) + { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return certValidityUndetermined; + } + + if ( SECSuccess != DER_DecodeTimeChoice(¬BeforeA, &val_a->notBefore) || + SECSuccess != DER_DecodeTimeChoice(¬BeforeB, &val_b->notBefore) || + SECSuccess != DER_DecodeTimeChoice(¬AfterA, &val_a->notAfter) || + SECSuccess != DER_DecodeTimeChoice(¬AfterB, &val_b->notAfter) ) { + return certValidityUndetermined; + } + + /* sanity check */ + if (LL_CMP(notBeforeA,>,notAfterA) || LL_CMP(notBeforeB,>,notAfterB)) { + PORT_SetError(SEC_ERROR_INVALID_TIME); + return certValidityUndetermined; + } + + if (LL_CMP(notAfterA,!=,notAfterB)) { + /* one cert validity goes farther into the future, select it */ + return LL_CMP(notAfterA,<,notAfterB) ? + certValidityChooseB : certValidityChooseA; + } + /* the two certs have the same expiration date */ + PORT_Assert(LL_CMP(notAfterA, == , notAfterB)); + /* do they also have the same start date ? */ + if (LL_CMP(notBeforeA,==,notBeforeB)) { + return certValidityEqual; + } + /* choose cert with the later start date */ + return LL_CMP(notBeforeA,<,notBeforeB) ? + certValidityChooseB : certValidityChooseA; +} /* * is certa newer than certb? If one is expired, pick the other one. diff --git a/security/nss/lib/certdb/certdb.h b/security/nss/lib/certdb/certdb.h index b24d470c4..f81fa93a7 100644 --- a/security/nss/lib/certdb/certdb.h +++ b/security/nss/lib/certdb/certdb.h @@ -157,6 +157,13 @@ SEC_CheckCRL(PCERTCertDBHandle *handle,PCERTCertificate *cert, SECStatus SEC_CrlReplaceUrl(PCERTSignedCrl *crl,char *url); + +/* Compare two certificate validity structures and return which cert should be +** preferred, based first on newer notAfter, then on newer notBefore. +*/ +CERTCompareValidityStatus +CERT_CompareValidityTimes(CERTValidity* val_a, CERTValidity* val_b); + #endif SEC_END_PROTOS diff --git a/security/nss/lib/certdb/certt.h b/security/nss/lib/certdb/certt.h index a513092c6..8567ebbe4 100644 --- a/security/nss/lib/certdb/certt.h +++ b/security/nss/lib/certdb/certt.h @@ -523,6 +523,21 @@ typedef enum SECCertTimeValidityEnum { } SECCertTimeValidity; /* + * This is used as return status in functions that compare the validity + * periods of two certificates A and B, currently only + * CERT_CompareValidityTimes. + */ + +typedef enum CERTCompareValidityStatusEnum +{ + certValidityUndetermined = 0, /* the function is unable to select one cert + over another */ + certValidityChooseB = 1, /* cert B should be preferred */ + certValidityEqual = 2, /* both certs have the same validity period */ + certValidityChooseA = 3 /* cert A should be preferred */ +} CERTCompareValidityStatus; + +/* * Interface for getting certificate nickname strings out of the database */ diff --git a/security/nss/lib/certdb/genname.c b/security/nss/lib/certdb/genname.c index 9c8d1a801..a5ac86e75 100644 --- a/security/nss/lib/certdb/genname.c +++ b/security/nss/lib/certdb/genname.c @@ -1462,6 +1462,7 @@ CERT_CompareNameSpace(CERTCertificate *cert, CERTNameConstraint *matchingConstraints; CERTCertificate *badCert = NULL; + constraintsExtension.data = NULL; rv = CERT_FindCertExtension(cert, SEC_OID_X509_NAME_CONSTRAINTS, &constraintsExtension); if (rv != SECSuccess) { @@ -1474,6 +1475,7 @@ CERT_CompareNameSpace(CERTCertificate *cert, } /* TODO: mark arena */ constraints = cert_DecodeNameConstraints(arena, &constraintsExtension); + PORT_Free(constraintsExtension.data); currentName = namesList; if (constraints == NULL) { /* decode failed */ rv = SECFailure; diff --git a/security/nss/lib/certhigh/certhigh.c b/security/nss/lib/certhigh/certhigh.c index 56e9695cd..2c0ffe7cb 100644 --- a/security/nss/lib/certhigh/certhigh.c +++ b/security/nss/lib/certhigh/certhigh.c @@ -743,6 +743,7 @@ CERT_FindCRLDistributionPoints (CERTCertificate *cert) { SECItem encodedExtenValue; SECStatus rv; + CERTCrlDistributionPoints *dps; encodedExtenValue.data = NULL; encodedExtenValue.len = 0; @@ -753,8 +754,11 @@ CERT_FindCRLDistributionPoints (CERTCertificate *cert) return (NULL); } - return (CERT_DecodeCRLDistributionPoints (cert->arena, - &encodedExtenValue)); + dps = CERT_DecodeCRLDistributionPoints(cert->arena, &encodedExtenValue); + + PORT_Free(encodedExtenValue.data); + + return dps; } /* From crl.c */ diff --git a/security/nss/lib/certhigh/certhtml.c b/security/nss/lib/certhigh/certhtml.c index f5ca082f8..11ce4f6c8 100644 --- a/security/nss/lib/certhigh/certhtml.c +++ b/security/nss/lib/certhigh/certhtml.c @@ -407,7 +407,6 @@ CERT_HTMLCertInfo(CERTCertificate *cert, PRBool showImages, PRBool showIssuer) char *notBefore, *notAfter; char *ret; char *nickname; - SECItem dummyitem; unsigned char fingerprint[16]; /* result of MD5, always 16 bytes */ char *fpstr; SECItem fpitem; @@ -435,12 +434,8 @@ CERT_HTMLCertInfo(CERTCertificate *cert, PRBool showImages, PRBool showIssuer) showImages = PR_FALSE; } - dummyitem.data = NULL; rv = CERT_FindCertExtension(cert, SEC_OID_NS_CERT_EXT_SUBJECT_LOGO, - &dummyitem); - if ( dummyitem.data ) { - PORT_Free(dummyitem.data); - } + NULL); if ( rv || !showImages ) { htmlcertstrings[1] = ""; @@ -468,13 +463,8 @@ CERT_HTMLCertInfo(CERTCertificate *cert, PRBool showImages, PRBool showIssuer) htmlcertstrings[5] = subject; - dummyitem.data = NULL; - rv = CERT_FindCertExtension(cert, SEC_OID_NS_CERT_EXT_ISSUER_LOGO, - &dummyitem); - if ( dummyitem.data ) { - PORT_Free(dummyitem.data); - } + NULL); if ( rv || !showImages ) { htmlcertstrings[7] = ""; @@ -500,6 +490,7 @@ CERT_HTMLCertInfo(CERTCertificate *cert, PRBool showImages, PRBool showIssuer) pubk = CERT_ExtractPublicKey(cert); DSSPriv = NULL; if (pubk && (pubk->keyType == fortezzaKey)) { + SECItem dummyitem; htmlcertstrings[18] = "</b><br><b>Clearance:</b>"; htmlcertstrings[19] = sec_FortezzaClearance( &pubk->u.fortezza.clearance); diff --git a/security/nss/lib/certhigh/certreq.c b/security/nss/lib/certhigh/certreq.c index 924067780..148b71746 100644 --- a/security/nss/lib/certhigh/certreq.c +++ b/security/nss/lib/certhigh/certreq.c @@ -126,6 +126,23 @@ CERT_CreateCertificate(unsigned long serialNumber, } /************************************************************************/ +/* It's clear from the comments that the original author of this + * function expected the template for certificate requests to treat + * the attributes as a SET OF ANY. This function expected to be + * passed an array of SECItems each of which contained an already encoded + * Attribute. But the cert request template does not treat the + * Attributes as a SET OF ANY, and AFAIK never has. Instead the template + * encodes attributes as a SET OF xxxxxxx. That is, it expects to encode + * each of the Attributes, not have them pre-encoded. Consequently an + * array of SECItems containing encoded Attributes is of no value to this + * function. But we cannot change the signature of this public function. + * It must continue to take SECItems. + * + * I have recoded this function so that each SECItem contains an + * encoded cert extension. The encoded cert extensions form the list for the + * single attribute of the cert request. In this implementation there is at most + * one attribute and it is always of type SEC_OID_PKCS9_EXTENSION_REQUEST. + */ CERTCertificateRequest * CERT_CreateCertificateRequest(CERTName *subject, @@ -134,88 +151,94 @@ CERT_CreateCertificateRequest(CERTName *subject, { CERTCertificateRequest *certreq; PRArenaPool *arena; + CERTAttribute * attribute; + SECOidData * oidData; SECStatus rv; + int i = 0; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if ( arena == NULL ) { return NULL; } - certreq = (CERTCertificateRequest *) - PORT_ArenaZAlloc(arena, sizeof(CERTCertificateRequest)); - - if (certreq != NULL) { - certreq->arena = arena; - - rv = DER_SetUInteger(arena, &certreq->version, - SEC_CERTIFICATE_REQUEST_VERSION); - if (rv != SECSuccess) - goto loser; - - rv = CERT_CopyName(arena, &certreq->subject, subject); - if (rv != SECSuccess) - goto loser; + certreq = PORT_ArenaZNew(arena, CERTCertificateRequest); + if (!certreq) { + PORT_FreeArena(arena, PR_FALSE); + return NULL; + } + /* below here it is safe to goto loser */ - rv = SECKEY_CopySubjectPublicKeyInfo(arena, - &certreq->subjectPublicKeyInfo, - spki); - if (rv != SECSuccess) + certreq->arena = arena; + + rv = DER_SetUInteger(arena, &certreq->version, + SEC_CERTIFICATE_REQUEST_VERSION); + if (rv != SECSuccess) + goto loser; + + rv = CERT_CopyName(arena, &certreq->subject, subject); + if (rv != SECSuccess) + goto loser; + + rv = SECKEY_CopySubjectPublicKeyInfo(arena, + &certreq->subjectPublicKeyInfo, + spki); + if (rv != SECSuccess) + goto loser; + + certreq->attributes = PORT_ArenaZNewArray(arena, CERTAttribute*, 2); + if(!certreq->attributes) + goto loser; + + /* Copy over attribute information */ + if (!attributes || !attributes[0]) { + /* + ** Invent empty attribute information. According to the + ** pkcs#10 spec, attributes has this ASN.1 type: + ** + ** attributes [0] IMPLICIT Attributes + ** + ** Which means, we should create a NULL terminated list + ** with the first entry being NULL; + */ + certreq->attributes[0] = NULL; + return certreq; + } + + /* allocate space for attributes */ + attribute = PORT_ArenaZNew(arena, CERTAttribute); + if (!attribute) + goto loser; + + oidData = SECOID_FindOIDByTag( SEC_OID_PKCS9_EXTENSION_REQUEST ); + PORT_Assert(oidData); + if (!oidData) + goto loser; + rv = SECITEM_CopyItem(arena, &attribute->attrType, &oidData->oid); + if (rv != SECSuccess) + goto loser; + + for (i = 0; attributes[i] != NULL ; i++) + ; + attribute->attrValue = PORT_ArenaZNewArray(arena, SECItem *, i+1); + if (!attribute->attrValue) + goto loser; + + /* copy attributes */ + for (i = 0; attributes[i]; i++) { + /* + ** Attributes are a SetOf Attribute which implies + ** lexigraphical ordering. It is assumes that the + ** attributes are passed in sorted. If we need to + ** add functionality to sort them, there is an + ** example in the PKCS 7 code. + */ + attribute->attrValue[i] = SECITEM_ArenaDupItem(arena, attributes[i]); + if(!attribute->attrValue[i]) goto loser; - - /* Copy over attribute information */ - if (attributes) { - int i = 0; - - /* allocate space for attributes */ - while(attributes[i] != NULL) i++; - certreq->attributes = PORT_ArenaZNewArray(arena,CERTAttribute*,i+1); - if(!certreq->attributes) { - goto loser; - } - - /* copy attributes */ - i = 0; - while(attributes[i]) { - /* - ** Attributes are a SetOf Attribute which implies - ** lexigraphical ordering. It is assumes that the - ** attributes are passed in sorted. If we need to - ** add functionality to sort them, there is an - ** example in the PKCS 7 code. - */ - certreq->attributes[i] = (SECItem*)PORT_ArenaZAlloc(arena, - sizeof(SECItem)); - if(!certreq->attributes[i]) { - goto loser; - }; - rv = SECITEM_CopyItem(arena, certreq->attributes[i], - attributes[i]); - if (rv != SECSuccess) { - goto loser; - } - i++; - } - certreq->attributes[i] = NULL; - } else { - /* - ** Invent empty attribute information. According to the - ** pkcs#10 spec, attributes has this ASN.1 type: - ** - ** attributes [0] IMPLICIT Attributes - ** - ** Which means, we should create a NULL terminated list - ** with the first entry being NULL; - */ - certreq->attributes = (SECItem**)PORT_ArenaZAlloc(arena, sizeof(SECItem *)); - if(!certreq->attributes) { - goto loser; - } - certreq->attributes[0] = NULL; - } - } else { - PORT_FreeArena(arena, PR_FALSE); } + certreq->attributes[0] = attribute; + return certreq; loser: diff --git a/security/nss/lib/certhigh/crlv2.c b/security/nss/lib/certhigh/crlv2.c index 3e9e0e44e..b6d8c9182 100644 --- a/security/nss/lib/certhigh/crlv2.c +++ b/security/nss/lib/certhigh/crlv2.c @@ -133,9 +133,8 @@ SECStatus CERT_FindInvalidDateExten (CERTCrl *crl, int64 *value) rv = SEC_ASN1DecodeItem (NULL, &decodedExtenValue, SEC_GeneralizedTimeTemplate, &encodedExtenValue); - if (rv != SECSuccess) - return (rv); - rv = DER_GeneralizedTimeToTime(value, &encodedExtenValue); + if (rv == SECSuccess) + rv = DER_GeneralizedTimeToTime(value, &encodedExtenValue); PORT_Free (decodedExtenValue.data); PORT_Free (encodedExtenValue.data); return (rv); diff --git a/security/nss/lib/certhigh/ocsp.c b/security/nss/lib/certhigh/ocsp.c index 54fa8ca24..9eda390b4 100644 --- a/security/nss/lib/certhigh/ocsp.c +++ b/security/nss/lib/certhigh/ocsp.c @@ -2296,14 +2296,9 @@ static PRBool ocsp_CertHasNoCheckExtension(CERTCertificate *cert) { SECStatus rv; - SECItem extItem; - extItem.data = NULL; rv = CERT_FindCertExtension(cert, SEC_OID_PKIX_OCSP_NO_CHECK, - &extItem); - if (extItem.data != NULL) { - PORT_Free(extItem.data); - } + NULL); if (rv == SECSuccess) { return PR_TRUE; } diff --git a/security/nss/lib/ckfw/builtins/Makefile b/security/nss/lib/ckfw/builtins/Makefile index 6301cae8b..d1410119c 100644 --- a/security/nss/lib/ckfw/builtins/Makefile +++ b/security/nss/lib/ckfw/builtins/Makefile @@ -48,34 +48,31 @@ EXTRA_LIBS = \ # can't do this in manifest.mn because OS_TARGET isn't defined there. ifeq (,$(filter-out WIN%,$(OS_TARGET))) -# Link with the real NSPR DLLs for MinGW because the NSPR stubs in -# nsprstub.c can't resolve the references to the _imp__PR_XXX symbols. -# This is merely an expedient hack and not the right solution. ifdef NS_USE_GCC EXTRA_LIBS += \ - -L$(DIST)/lib \ + -L$(NSPR_LIB_DIR) \ -lplc4 \ -lplds4 \ -lnspr4 \ $(NULL) -else -EXTRA_LIBS += \ - $(DIST)/lib/$(NSPR31_LIB_PREFIX)plc4_s.lib \ - $(DIST)/lib/$(NSPR31_LIB_PREFIX)plds4_s.lib \ - $(NULL) -endif - +else +EXTRA_SHARED_LIBS += \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \ + $(NULL) +endif # NS_USE_GCC else EXTRA_LIBS += \ - $(DIST)/lib/$(LIB_PREFIX)plc4.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)plds4.$(LIB_SUFFIX) \ + -L$(NSPR_LIB_DIR) \ + -lplc4 \ + -lplds4 \ + -lnspr4 \ $(NULL) - endif - include $(CORE_DEPTH)/coreconf/rules.mk # Generate certdata.c. diff --git a/security/nss/lib/ckfw/builtins/nssckbi.h b/security/nss/lib/ckfw/builtins/nssckbi.h index 951aa4365..b0378eea9 100644 --- a/security/nss/lib/ckfw/builtins/nssckbi.h +++ b/security/nss/lib/ckfw/builtins/nssckbi.h @@ -48,7 +48,7 @@ * to the PKCS #11 spec versions. */ #define NSS_BUILTINS_CRYPTOKI_VERSION_MAJOR 2 -#define NSS_BUILTINS_CRYPTOKI_VERSION_MINOR 1 +#define NSS_BUILTINS_CRYPTOKI_VERSION_MINOR 20 /* These version numbers detail the changes * to the list of trusted certificates. @@ -64,6 +64,7 @@ * - NSS 3.8 branch: 30-39 * - NSS 3.9 branch: 40-49 * - NSS 3.10 branch: 50-59 + * - NSS 3.11 branch: 60-69 * ... * - NSS 3.14 branch: 90-99 * ... @@ -74,8 +75,8 @@ * of the comment in the CK_VERSION type definition. */ #define NSS_BUILTINS_LIBRARY_VERSION_MAJOR 1 -#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 53 -#define NSS_BUILTINS_LIBRARY_VERSION "1.53" +#define NSS_BUILTINS_LIBRARY_VERSION_MINOR 60 +#define NSS_BUILTINS_LIBRARY_VERSION "1.60" /* These version numbers detail the semantic changes to the ckfw engine. */ #define NSS_BUILTINS_HARDWARE_VERSION_MAJOR 1 diff --git a/security/nss/lib/ckfw/capi/Makefile b/security/nss/lib/ckfw/capi/Makefile new file mode 100644 index 000000000..77afe8097 --- /dev/null +++ b/security/nss/lib/ckfw/capi/Makefile @@ -0,0 +1,105 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is the Netscape security libraries. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1994-2000 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** +MAKEFILE_CVS_ID = "@(#) $RCSfile$ $Revision$ $Date$" + +include manifest.mn +include $(CORE_DEPTH)/coreconf/config.mk +include config.mk + +EXTRA_LIBS = \ + $(DIST)/lib/$(LIB_PREFIX)nssckfw.$(LIB_SUFFIX) \ + $(DIST)/lib/$(LIB_PREFIX)nssb.$(LIB_SUFFIX) \ + $(NULL) + +# can't do this in manifest.mn because OS_TARGET isn't defined there. +ifeq (,$(filter-out WIN%,$(OS_TARGET))) + +ifdef NS_USE_GCC +EXTRA_LIBS += \ + -L$(NSPR_LIB_DIR) \ + -lplc4 \ + -lplds4 \ + -lnspr4 \ + $(NULL) +else +EXTRA_SHARED_LIBS += \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \ + crypt32.lib \ + advapi32.lib \ + rpcrt4.lib \ + $(NULL) +endif # NS_USE_GCC +else + +EXTRA_LIBS += \ + -L$(NSPR_LIB_DIR) \ + -lplc4 \ + -lplds4 \ + -lnspr4 \ + $(NULL) +endif + + +include $(CORE_DEPTH)/coreconf/rules.mk + +# Generate certdata.c. +generate: + perl certdata.perl < certdata.txt + +# This'll need some help from a build person. + + +ifeq ($(OS_TARGET)$(OS_RELEASE), AIX4.1) +DSO_LDOPTS = -bM:SRE -bh:4 -bnoentry +EXTRA_DSO_LDOPTS = -lc +MKSHLIB = xlC $(DSO_LDOPTS) + +$(SHARED_LIBRARY): $(OBJS) + @$(MAKE_OBJDIR) + rm -f $@ + $(MKSHLIB) -o $@ $(OBJS) $(EXTRA_LIBS) $(EXTRA_DSO_LDOPTS) + chmod +x $@ + +endif + +ifeq ($(OS_TARGET)$(OS_RELEASE), AIX4.2) +LD += -G +endif + + diff --git a/security/nss/lib/ckfw/capi/README b/security/nss/lib/ckfw/capi/README new file mode 100644 index 000000000..9fc5720a9 --- /dev/null +++ b/security/nss/lib/ckfw/capi/README @@ -0,0 +1,7 @@ +This Cryptoki module provides acces to certs and keys stored in +Microsofts CAPI certificate store. + +It does not import or export CA Root trust from the CAPI. +It does not import or export CRLs from the CAPI. +It does not handle S/MIME objects (pkcs #7 in capi terms?). +It does not yet handle it's own PIN. (CAPI does all the pin prompting). diff --git a/security/nss/lib/ckfw/capi/anchor.c b/security/nss/lib/ckfw/capi/anchor.c new file mode 100644 index 000000000..e21006621 --- /dev/null +++ b/security/nss/lib/ckfw/capi/anchor.c @@ -0,0 +1,55 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * Portions created by Red Hat, Inc, are Copyright (C) 2005 + * + * Contributor(s): + * Bob Relyea (rrelyea@redhat.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifdef DEBUG +static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$"; +#endif /* DEBUG */ + +/* + * capi/canchor.c + * + * This file "anchors" the actual cryptoki entry points in this module's + * shared library, which is required for dynamic loading. See the + * comments in nssck.api for more information. + */ + +#include "ckcapi.h" + +#define MODULE_NAME ckcapi +#define INSTANCE_NAME (NSSCKMDInstance *)&nss_ckcapi_mdInstance +#include "nssck.api" diff --git a/security/nss/lib/ckfw/capi/cfind.c b/security/nss/lib/ckfw/capi/cfind.c new file mode 100644 index 000000000..b685c0888 --- /dev/null +++ b/security/nss/lib/ckfw/capi/cfind.c @@ -0,0 +1,595 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * Portions created by Red Hat, Inc, are Copyright (C) 2005 + * + * Contributor(s): + * Bob Relyea (rrelyea@redhat.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifdef DEBUG +static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$"; +#endif /* DEBUG */ + +#ifndef CKCAPI_H +#include "ckcapi.h" +#endif /* CKCAPI_H */ + +/* + * ckcapi/cfind.c + * + * This file implements the NSSCKMDFindObjects object for the + * "capi" cryptoki module. + */ + +struct ckcapiFOStr { + NSSArena *arena; + CK_ULONG n; + CK_ULONG i; + ckcapiInternalObject **objs; +}; + +static void +ckcapi_mdFindObjects_Final +( + NSSCKMDFindObjects *mdFindObjects, + NSSCKFWFindObjects *fwFindObjects, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance +) +{ + struct ckcapiFOStr *fo = (struct ckcapiFOStr *)mdFindObjects->etc; + NSSArena *arena = fo->arena; + PRUint32 i; + + /* walk down an free the unused 'objs' */ + for (i=fo->i; i < fo->n ; i++) { + nss_ckcapi_DestroyInternalObject(fo->objs[i]); + } + + nss_ZFreeIf(fo->objs); + nss_ZFreeIf(fo); + nss_ZFreeIf(mdFindObjects); + if ((NSSArena *)NULL != arena) { + NSSArena_Destroy(arena); + } + + return; +} + +static NSSCKMDObject * +ckcapi_mdFindObjects_Next +( + NSSCKMDFindObjects *mdFindObjects, + NSSCKFWFindObjects *fwFindObjects, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + NSSArena *arena, + CK_RV *pError +) +{ + struct ckcapiFOStr *fo = (struct ckcapiFOStr *)mdFindObjects->etc; + ckcapiInternalObject *io; + + if( fo->i == fo->n ) { + *pError = CKR_OK; + return (NSSCKMDObject *)NULL; + } + + io = fo->objs[ fo->i ]; + fo->i++; + + return nss_ckcapi_CreateMDObject(arena, io, pError); +} + +static CK_BBOOL +ckcapi_attrmatch +( + CK_ATTRIBUTE_PTR a, + ckcapiInternalObject *o +) +{ + PRBool prb; + const NSSItem *b; + + b = nss_ckcapi_FetchAttribute(o, a->type); + if (b == NULL) { + return CK_FALSE; + } + + if( a->ulValueLen != b->size ) { + /* match a decoded serial number */ + if ((a->type == CKA_SERIAL_NUMBER) && (a->ulValueLen < b->size)) { + int len; + unsigned char *data; + + data = nss_ckcapi_DERUnwrap(b->data, b->size, &len, NULL); + if ((len == a->ulValueLen) && + nsslibc_memequal(a->pValue, data, len, (PRStatus *)NULL)) { + return CK_TRUE; + } + } + return CK_FALSE; + } + + prb = nsslibc_memequal(a->pValue, b->data, b->size, (PRStatus *)NULL); + + if( PR_TRUE == prb ) { + return CK_TRUE; + } else { + return CK_FALSE; + } +} + + +static CK_BBOOL +ckcapi_match +( + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + ckcapiInternalObject *o +) +{ + CK_ULONG i; + + for( i = 0; i < ulAttributeCount; i++ ) { + if (CK_FALSE == ckcapi_attrmatch(&pTemplate[i], o)) { + return CK_FALSE; + } + } + + /* Every attribute passed */ + return CK_TRUE; +} + +#define CKAPI_ITEM_CHUNK 20 + +#define PUT_Object(obj,err) \ + { \ + if (count >= size) { \ + *listp = *listp ? \ + nss_ZREALLOCARRAY(*listp, ckcapiInternalObject *, \ + (size+CKAPI_ITEM_CHUNK) ) : \ + nss_ZNEWARRAY(NULL, ckcapiInternalObject *, \ + (size+CKAPI_ITEM_CHUNK) ) ; \ + if ((ckcapiInternalObject **)NULL == *listp) { \ + err = CKR_HOST_MEMORY; \ + goto loser; \ + } \ + size += CKAPI_ITEM_CHUNK; \ + } \ + (*listp)[ count ] = (obj); \ + count++; \ + } + + +/* + * pass parameters back through the callback. + */ +typedef struct BareCollectParamsStr { + CK_OBJECT_CLASS objClass; + CK_ATTRIBUTE_PTR pTemplate; + CK_ULONG ulAttributeCount; + ckcapiInternalObject ***listp; + PRUint32 size; + PRUint32 count; +} BareCollectParams; + +/* collect_bare's callback. Called for each object that + * supposedly has a PROVINDER_INFO property */ +static BOOL WINAPI +doBareCollect +( + const CRYPT_HASH_BLOB *msKeyID, + DWORD flags, + void *reserved, + void *args, + DWORD cProp, + DWORD *propID, + void **propData, + DWORD *propSize +) +{ + BareCollectParams *bcp = (BareCollectParams *) args; + PRUint32 size = bcp->size; + PRUint32 count = bcp->count; + ckcapiInternalObject ***listp = bcp->listp; + ckcapiInternalObject *io = NULL; + DWORD i; + CRYPT_KEY_PROV_INFO *keyProvInfo = NULL; + void *idData; + CK_RV error; + + /* make sure there is a Key Provider Info property */ + for (i=0; i < cProp; i++) { + if (CERT_KEY_PROV_INFO_PROP_ID == propID[i]) { + keyProvInfo = (CRYPT_KEY_PROV_INFO *)propData[i]; + break; + } + } + if ((CRYPT_KEY_PROV_INFO *)NULL == keyProvInfo) { + return 1; + } + + /* copy the key ID */ + idData = nss_ZNEWARRAY(NULL, char, msKeyID->cbData); + if ((void *)NULL == idData) { + goto loser; + } + nsslibc_memcpy(idData, msKeyID->pbData, msKeyID->cbData); + + /* build a bare internal object */ + io = nss_ZNEW(NULL, ckcapiInternalObject); + if ((ckcapiInternalObject *)NULL == io) { + goto loser; + } + io->type = ckcapiBareKey; + io->objClass = bcp->objClass; + io->u.key.provInfo = *keyProvInfo; + io->u.key.provInfo.pwszContainerName = + nss_ckcapi_WideDup(keyProvInfo->pwszContainerName); + io->u.key.provInfo.pwszProvName = + nss_ckcapi_WideDup(keyProvInfo->pwszProvName); + io->u.key.provName = nss_ckcapi_WideToUTF8(keyProvInfo->pwszProvName); + io->u.key.containerName = + nss_ckcapi_WideToUTF8(keyProvInfo->pwszContainerName); + io->u.key.hProv = 0; + io->idData = idData; + io->id.data = idData; + io->id.size = msKeyID->cbData; + idData = NULL; + + /* see if it matches */ + if( CK_FALSE == ckcapi_match(bcp->pTemplate, bcp->ulAttributeCount, io) ) { + goto loser; + } + PUT_Object(io, error); + bcp->size = size; + bcp->count = count; + return 1; + +loser: + if (io) { + nss_ckcapi_DestroyInternalObject(io); + } + nss_ZFreeIf(idData); + return 1; +} + +/* + * collect the bare keys running around + */ +static PRUint32 +collect_bare( + CK_OBJECT_CLASS objClass, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + ckcapiInternalObject ***listp, + PRUint32 *sizep, + PRUint32 count, + CK_RV *pError +) +{ + BOOL rc; + BareCollectParams bareCollectParams; + + bareCollectParams.objClass = objClass; + bareCollectParams.pTemplate = pTemplate; + bareCollectParams.ulAttributeCount = ulAttributeCount; + bareCollectParams.listp = listp; + bareCollectParams.size = *sizep; + bareCollectParams.count = count; + + rc = CryptEnumKeyIdentifierProperties(NULL, CERT_KEY_PROV_INFO_PROP_ID, 0, + NULL, NULL, &bareCollectParams, doBareCollect); + + *sizep = bareCollectParams.size; + return bareCollectParams.count; +} + +/* find all the certs that represent the appropriate object (cert, priv key, or + * pub key) in the cert store. + */ +static PRUint32 +collect_class( + CK_OBJECT_CLASS objClass, + LPCSTR storeStr, + PRBool hasID, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + ckcapiInternalObject ***listp, + PRUint32 *sizep, + PRUint32 count, + CK_RV *pError +) +{ + PRUint32 size = *sizep; + ckcapiInternalObject *next = NULL; + HCERTSTORE hStore; + PCCERT_CONTEXT certContext = NULL; + PRBool isKey = + (objClass == CKO_PUBLIC_KEY) | (objClass == CKO_PRIVATE_KEY); + + hStore = CertOpenSystemStore((HCRYPTPROV)NULL, storeStr); + if (NULL == hStore) { + return count; /* none found does not imply an error */ + } + + /* FUTURE: use CertFindCertificateInStore to filter better -- so we don't + * have to enumerate all the certificates */ + while ((PCERT_CONTEXT) NULL != + (certContext= CertEnumCertificatesInStore(hStore, certContext))) { + /* first filter out non user certs if we are looking for keys */ + if (isKey) { + /* make sure there is a Key Provider Info property */ + CRYPT_KEY_PROV_INFO key_prov; + DWORD size = sizeof(CRYPT_KEY_PROV_INFO); + BOOL rv; + rv =CertGetCertificateContextProperty(certContext, + CERT_KEY_PROV_INFO_PROP_ID, &key_prov, &size); + if (!rv) { + int reason = GetLastError(); + /* we only care if it exists, we don't really need to fetch it yet */ + if (reason == CRYPT_E_NOT_FOUND) { + continue; + } + } + } + + if ((ckcapiInternalObject *)NULL == next) { + next = nss_ZNEW(NULL, ckcapiInternalObject); + if ((ckcapiInternalObject *)NULL == next) { + *pError = CKR_HOST_MEMORY; + goto loser; + } + } + next->type = ckcapiCert; + next->objClass = objClass; + next->u.cert.certContext = certContext; + next->u.cert.hasID = hasID; + next->u.cert.certStore = storeStr; + if( CK_TRUE == ckcapi_match(pTemplate, ulAttributeCount, next) ) { + /* clear cached values that may be dependent on our old certContext */ + memset(&next->u.cert, 0, sizeof(next->u.cert)); + /* get a 'permanent' context */ + next->u.cert.certContext = CertDuplicateCertificateContext(certContext); + next->objClass = objClass; + next->u.cert.certContext = certContext; + next->u.cert.hasID = hasID; + next->u.cert.certStore = storeStr; + PUT_Object(next, *pError); + next = NULL; /* need to allocate a new one now */ + } else { + /* don't cache the values we just loaded */ + memset(&next->u.cert, 0, sizeof(next->u.cert)); + } + } +loser: + CertCloseStore(hStore, 0); + nss_ZFreeIf(next); + *sizep = size; + return count; +} + +NSS_IMPLEMENT PRUint32 +nss_ckcapi_collect_all_certs( + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + ckcapiInternalObject ***listp, + PRUint32 *sizep, + PRUint32 count, + CK_RV *pError +) +{ + count = collect_class(CKO_CERTIFICATE, "My", PR_TRUE, pTemplate, + ulAttributeCount, listp, sizep, count, pError); + count = collect_class(CKO_CERTIFICATE, "AddressBook", PR_FALSE, pTemplate, + ulAttributeCount, listp, sizep, count, pError); + count = collect_class(CKO_CERTIFICATE, "CA", PR_FALSE, pTemplate, + ulAttributeCount, listp, sizep, count, pError); + count = collect_class(CKO_CERTIFICATE, "Root", PR_FALSE, pTemplate, + ulAttributeCount, listp, sizep, count, pError); + count = collect_class(CKO_CERTIFICATE, "Trust", PR_FALSE, pTemplate, + ulAttributeCount, listp, sizep, count, pError); + count = collect_class(CKO_CERTIFICATE, "TrustedPeople", PR_FALSE, pTemplate, + ulAttributeCount, listp, sizep, count, pError); + count = collect_class(CKO_CERTIFICATE, "AuthRoot", PR_FALSE, pTemplate, + ulAttributeCount, listp, sizep, count, pError); + return count; +} + +CK_OBJECT_CLASS +ckcapi_GetObjectClass(CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount) +{ + CK_ULONG i; + + for (i=0; i < ulAttributeCount; i++) + { + if (pTemplate[i].type == CKA_CLASS) { + return *(CK_OBJECT_CLASS *) pTemplate[i].pValue; + } + } + /* need to return a value that says 'fetch them all' */ + return CK_INVALID_HANDLE; +} + +static PRUint32 +collect_objects( + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + ckcapiInternalObject ***listp, + CK_RV *pError +) +{ + PRUint32 i; + PRUint32 count = 0; + PRUint32 size = 0; + CK_OBJECT_CLASS objClass; + + /* + * first handle the static build in objects (if any) + */ + for( i = 0; i < nss_ckcapi_nObjects; i++ ) { + ckcapiInternalObject *o = (ckcapiInternalObject *)&nss_ckcapi_data[i]; + + if( CK_TRUE == ckcapi_match(pTemplate, ulAttributeCount, o) ) { + PUT_Object(o, *pError); + } + } + + /* + * now handle the various object types + */ + objClass = ckcapi_GetObjectClass(pTemplate, ulAttributeCount); + *pError = CKR_OK; + switch (objClass) { + case CKO_CERTIFICATE: + count = nss_ckcapi_collect_all_certs(pTemplate, ulAttributeCount, listp, + &size, count, pError); + break; + case CKO_PUBLIC_KEY: + count = collect_class(objClass, "My", PR_TRUE, pTemplate, + ulAttributeCount, listp, &size, count, pError); + count = collect_bare(objClass, pTemplate, ulAttributeCount, listp, + &size, count, pError); + break; + case CKO_PRIVATE_KEY: + count = collect_class(objClass, "My", PR_TRUE, pTemplate, + ulAttributeCount, listp, &size, count, pError); + count = collect_bare(objClass, pTemplate, ulAttributeCount, listp, + &size, count, pError); + break; + /* all of them */ + case CK_INVALID_HANDLE: + count = nss_ckcapi_collect_all_certs(pTemplate, ulAttributeCount, listp, + &size, count, pError); + count = collect_class(CKO_PUBLIC_KEY, "My", PR_TRUE, pTemplate, + ulAttributeCount, listp, &size, count, pError); + count = collect_bare(CKO_PUBLIC_KEY, pTemplate, ulAttributeCount, listp, + &size, count, pError); + count = collect_class(CKO_PRIVATE_KEY, "My", PR_TRUE, pTemplate, + ulAttributeCount, listp, &size, count, pError); + count = collect_bare(CKO_PRIVATE_KEY, pTemplate, ulAttributeCount, listp, + &size, count, pError); + break; + default: + goto done; /* no other object types we understand in this module */ + } + if (CKR_OK != *pError) { + goto loser; + } + + +done: + return count; +loser: + nss_ZFreeIf(*listp); + return 0; +} + + + +NSS_IMPLEMENT NSSCKMDFindObjects * +nss_ckcapi_FindObjectsInit +( + NSSCKFWSession *fwSession, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + CK_RV *pError +) +{ + /* This could be made more efficient. I'm rather rushed. */ + NSSArena *arena; + NSSCKMDFindObjects *rv = (NSSCKMDFindObjects *)NULL; + struct ckcapiFOStr *fo = (struct ckcapiFOStr *)NULL; + ckcapiInternalObject **temp = (ckcapiInternalObject **)NULL; + + arena = NSSArena_Create(); + if( (NSSArena *)NULL == arena ) { + goto loser; + } + + rv = nss_ZNEW(arena, NSSCKMDFindObjects); + if( (NSSCKMDFindObjects *)NULL == rv ) { + *pError = CKR_HOST_MEMORY; + goto loser; + } + + fo = nss_ZNEW(arena, struct ckcapiFOStr); + if( (struct ckcapiFOStr *)NULL == fo ) { + *pError = CKR_HOST_MEMORY; + goto loser; + } + + fo->arena = arena; + /* fo->n and fo->i are already zero */ + + rv->etc = (void *)fo; + rv->Final = ckcapi_mdFindObjects_Final; + rv->Next = ckcapi_mdFindObjects_Next; + rv->null = (void *)NULL; + + fo->n = collect_objects(pTemplate, ulAttributeCount, &temp, pError); + if (*pError != CKR_OK) { + goto loser; + } + + fo->objs = nss_ZNEWARRAY(arena, ckcapiInternalObject *, fo->n); + if( (ckcapiInternalObject **)NULL == fo->objs ) { + *pError = CKR_HOST_MEMORY; + goto loser; + } + + (void)nsslibc_memcpy(fo->objs, temp, sizeof(ckcapiInternalObject *) * fo->n); + nss_ZFreeIf(temp); + temp = (ckcapiInternalObject **)NULL; + + return rv; + + loser: + nss_ZFreeIf(temp); + nss_ZFreeIf(fo); + nss_ZFreeIf(rv); + if ((NSSArena *)NULL != arena) { + NSSArena_Destroy(arena); + } + return (NSSCKMDFindObjects *)NULL; +} + diff --git a/security/nss/lib/ckfw/capi/cinst.c b/security/nss/lib/ckfw/capi/cinst.c new file mode 100644 index 000000000..fe5c3d25e --- /dev/null +++ b/security/nss/lib/ckfw/capi/cinst.c @@ -0,0 +1,148 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * Portions created by Red Hat, Inc, are Copyright (C) 2005 + * + * Contributor(s): + * Bob Relyea (rrelyea@redhat.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifdef DEBUG +static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$"; +#endif /* DEBUG */ + +#include "ckcapi.h" + +/* + * ckcapi/cinstance.c + * + * This file implements the NSSCKMDInstance object for the + * "capi" cryptoki module. + */ + +/* + * NSSCKMDInstance methods + */ + +static CK_ULONG +ckcapi_mdInstance_GetNSlots +( + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError +) +{ + return (CK_ULONG)1; +} + +static CK_VERSION +ckcapi_mdInstance_GetCryptokiVersion +( + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance +) +{ + return nss_ckcapi_CryptokiVersion; +} + +static NSSUTF8 * +ckcapi_mdInstance_GetManufacturerID +( + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError +) +{ + return (NSSUTF8 *)nss_ckcapi_ManufacturerID; +} + +static NSSUTF8 * +ckcapi_mdInstance_GetLibraryDescription +( + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError +) +{ + return (NSSUTF8 *)nss_ckcapi_LibraryDescription; +} + +static CK_VERSION +ckcapi_mdInstance_GetLibraryVersion +( + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance +) +{ + return nss_ckcapi_LibraryVersion; +} + +static CK_RV +ckcapi_mdInstance_GetSlots +( + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + NSSCKMDSlot *slots[] +) +{ + slots[0] = (NSSCKMDSlot *)&nss_ckcapi_mdSlot; + return CKR_OK; +} + +static CK_BBOOL +ckcapi_mdInstance_ModuleHandlesSessionObjects +( + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance +) +{ + /* we don't want to allow any session object creation, at least + * until we can investigate whether or not we can use those objects + */ + return CK_TRUE; +} + +NSS_IMPLEMENT_DATA const NSSCKMDInstance +nss_ckcapi_mdInstance = { + (void *)NULL, /* etc */ + NULL, /* Initialize */ + NULL, /* Finalize */ + ckcapi_mdInstance_GetNSlots, + ckcapi_mdInstance_GetCryptokiVersion, + ckcapi_mdInstance_GetManufacturerID, + ckcapi_mdInstance_GetLibraryDescription, + ckcapi_mdInstance_GetLibraryVersion, + ckcapi_mdInstance_ModuleHandlesSessionObjects, + /*NULL, /* HandleSessionObjects */ + ckcapi_mdInstance_GetSlots, + NULL, /* WaitForSlotEvent */ + (void *)NULL /* null terminator */ +}; diff --git a/security/nss/lib/ckfw/capi/ckcapi.h b/security/nss/lib/ckfw/capi/ckcapi.h new file mode 100644 index 000000000..fb434ce57 --- /dev/null +++ b/security/nss/lib/ckfw/capi/ckcapi.h @@ -0,0 +1,309 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * Portions created by Red Hat, Inc, are Copyright (C) 2005 + * + * Contributor(s): + * Bob Relyea (rrelyea@redhat.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef CKCAPI_H +#define CKCAPI_H 1 + +#ifdef DEBUG +static const char CKCAPI_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$"; +#endif /* DEBUG */ + +#include "nssckmdt.h" +#include "nssckfw.h" + +/* + * I'm including this for access to the arena functions. + * Looks like we should publish that API. + */ +#ifndef BASE_H +#include "base.h" +#endif /* BASE_H */ + +/* + * This is where the Netscape extensions live, at least for now. + */ +#ifndef CKT_H +#include "ckt.h" +#endif /* CKT_H */ + +#include "WTypes.h" +#include "WinCrypt.h" + +/* + * statically defined raw objects. Allows us to data description objects + * to this PKCS #11 module. + */ +struct ckcapiRawObjectStr { + CK_ULONG n; + const CK_ATTRIBUTE_TYPE *types; + const NSSItem *items; +}; +typedef struct ckcapiRawObjectStr ckcapiRawObject; + + +/* + * common values needed for both bare keys and cert referenced keys. + */ +struct ckcapiKeyParamsStr { + NSSItem modulus; + NSSItem exponent; + NSSItem privateExponent; + NSSItem prime1; + NSSItem prime2; + NSSItem exponent1; + NSSItem exponent2; + NSSItem coefficient; + unsigned char publicExponentData[sizeof(CK_ULONG)]; + void *privateKey; + void *pubKey; +}; +typedef struct ckcapiKeyParamsStr ckcapiKeyParams; + +/* + * Key objects. Handles bare keys which do not yet have certs associated + * with them. These are usually short lived, but may exist for several days + * while the CA is issuing the certificate. + */ +struct ckcapiKeyObjectStr { + CRYPT_KEY_PROV_INFO provInfo; + char *provName; + char *containerName; + HCRYPTPROV hProv; + ckcapiKeyParams key; +}; +typedef struct ckcapiKeyObjectStr ckcapiKeyObject; + +/* + * Certificate and certificate referenced keys. + */ +struct ckcapiCertObjectStr { + PCCERT_CONTEXT certContext; + PRBool hasID; + const char *certStore; + NSSItem label; + NSSItem subject; + NSSItem issuer; + NSSItem serial; + NSSItem derCert; + ckcapiKeyParams key; + unsigned char *labelData; + /* static data: to do, make this dynamic like labelData */ + unsigned char derSerial[128]; +}; +typedef struct ckcapiCertObjectStr ckcapiCertObject; + +typedef enum { + ckcapiRaw, + ckcapiCert, + ckcapiBareKey +} ckcapiObjectType; + +/* + * all the various types of objects are abstracted away in cobject and + * cfind as ckcapiInternalObjects. + */ +struct ckcapiInternalObjectStr { + ckcapiObjectType type; + union { + ckcapiRawObject raw; + ckcapiCertObject cert; + ckcapiKeyObject key; + } u; + CK_OBJECT_CLASS objClass; + NSSItem hashKey; + NSSItem id; + void *idData; + unsigned char hashKeyData[128]; + NSSCKMDObject mdObject; +}; +typedef struct ckcapiInternalObjectStr ckcapiInternalObject; + +/* our raw object data array */ +NSS_EXTERN_DATA ckcapiInternalObject nss_ckcapi_data[]; +NSS_EXTERN_DATA const PRUint32 nss_ckcapi_nObjects; + +NSS_EXTERN_DATA const CK_VERSION nss_ckcapi_CryptokiVersion; +NSS_EXTERN_DATA const NSSUTF8 * nss_ckcapi_ManufacturerID; +NSS_EXTERN_DATA const NSSUTF8 * nss_ckcapi_LibraryDescription; +NSS_EXTERN_DATA const CK_VERSION nss_ckcapi_LibraryVersion; +NSS_EXTERN_DATA const NSSUTF8 * nss_ckcapi_SlotDescription; +NSS_EXTERN_DATA const CK_VERSION nss_ckcapi_HardwareVersion; +NSS_EXTERN_DATA const CK_VERSION nss_ckcapi_FirmwareVersion; +NSS_EXTERN_DATA const NSSUTF8 * nss_ckcapi_TokenLabel; +NSS_EXTERN_DATA const NSSUTF8 * nss_ckcapi_TokenModel; +NSS_EXTERN_DATA const NSSUTF8 * nss_ckcapi_TokenSerialNumber; + +NSS_EXTERN_DATA const NSSCKMDInstance nss_ckcapi_mdInstance; +NSS_EXTERN_DATA const NSSCKMDSlot nss_ckcapi_mdSlot; +NSS_EXTERN_DATA const NSSCKMDToken nss_ckcapi_mdToken; +NSS_EXTERN_DATA const NSSCKMDMechanism nss_ckcapi_mdMechanismRSA; + +NSS_EXTERN NSSCKMDSession * +nss_ckcapi_CreateSession +( + NSSCKFWSession *fwSession, + CK_RV *pError +); + +NSS_EXTERN NSSCKMDFindObjects * +nss_ckcapi_FindObjectsInit +( + NSSCKFWSession *fwSession, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + CK_RV *pError +); + +/* + * Object Utilities + */ +NSS_EXTERN NSSCKMDObject * +nss_ckcapi_CreateMDObject +( + NSSArena *arena, + ckcapiInternalObject *io, + CK_RV *pError +); + +NSS_EXTERN NSSCKMDObject * +nss_ckcapi_CreateObject +( + NSSCKFWSession *fwSession, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + CK_RV *pError +); + +NSS_EXTERN const NSSItem * +nss_ckcapi_FetchAttribute +( + ckcapiInternalObject *io, + CK_ATTRIBUTE_TYPE type +); + +NSS_EXTERN void +nss_ckcapi_DestroyInternalObject +( + ckcapiInternalObject *io +); + +NSS_EXTERN CK_RV +nss_ckcapi_FetchKeyContainer +( + ckcapiInternalObject *iKey, + HCRYPTPROV *hProv, + DWORD *keySpec, + HCRYPTKEY *hKey +); + +/* + * generic utilities + */ + +/* + * So everyone else in the worlds stores their bignum data MSB first, but not + * Microsoft, we need to byte swap everything coming into and out of CAPI. + */ +void +ckcapi_ReverseData +( + NSSItem *item +); + +/* + * unwrap a single DER value + */ +char * +nss_ckcapi_DERUnwrap +( + char *src, + int size, + int *outSize, + char **next +); + +/* + * Return the size in bytes of a wide string + */ +int +nss_ckcapi_WideSize +( + LPCWSTR wide +); + +/* + * Covert a Unicode wide character string to a UTF8 string + */ +char * +nss_ckcapi_WideToUTF8 +( + LPCWSTR wide +); + +/* + * Return a Wide String duplicated with nss allocated memory. + */ +LPWSTR +nss_ckcapi_WideDup +( + LPCWSTR wide +); + +/* + * Covert a UTF8 string to Unicode wide character + */ +LPWSTR +nss_ckcapi_UTF8ToWide +( + char *buf +); + + +NSS_EXTERN PRUint32 +nss_ckcapi_collect_all_certs( + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + ckcapiInternalObject ***listp, + PRUint32 *sizep, + PRUint32 count, + CK_RV *pError +); + +#define NSS_CKCAPI_ARRAY_SIZE(x) ((sizeof (x))/(sizeof ((x)[0]))) + +#endif diff --git a/security/nss/lib/ckfw/capi/ckcapiver.c b/security/nss/lib/ckfw/capi/ckcapiver.c new file mode 100644 index 000000000..d69290575 --- /dev/null +++ b/security/nss/lib/ckfw/capi/ckcapiver.c @@ -0,0 +1,59 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * Portions created by Red Hat, Inc, are Copyright (C) 2005 + * + * Contributor(s): + * Bob Relyea (rrelyea@redhat.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* Library identity and versioning */ + +#include "nsscapi.h" + +#if defined(DEBUG) +#define _DEBUG_STRING " (debug)" +#else +#define _DEBUG_STRING "" +#endif + +/* + * Version information for the 'ident' and 'what commands + * + * NOTE: the first component of the concatenated rcsid string + * must not end in a '$' to prevent rcs keyword substitution. + */ +const char __nss_ckcapi_rcsid[] = "$Header: NSS Access to Microsoft Certificate Store " + NSS_CKCAPI_LIBRARY_VERSION _DEBUG_STRING + " " __DATE__ " " __TIME__ " $"; +const char __nss_ckcapi_sccsid[] = "@(#)NSS Access to Microsoft Certificate Store " + NSS_CKCAPI_LIBRARY_VERSION _DEBUG_STRING + " " __DATE__ " " __TIME__; diff --git a/security/nss/lib/ckfw/capi/cobject.c b/security/nss/lib/ckfw/capi/cobject.c new file mode 100644 index 000000000..c12971ff5 --- /dev/null +++ b/security/nss/lib/ckfw/capi/cobject.c @@ -0,0 +1,2346 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * Portions created by Red Hat, Inc, are Copyright (C) 2005 + * + * Contributor(s): + * Bob Relyea (rrelyea@redhat.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifdef DEBUG +static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$"; +#endif /* DEBUG */ + +#include "ckcapi.h" +#include "nssbase.h" + +/* + * ckcapi/cobject.c + * + * This file implements the NSSCKMDObject object for the + * "nss to capi objects" cryptoki module. + */ + +const CK_ATTRIBUTE_TYPE certAttrs[] = { + CKA_CLASS, + CKA_TOKEN, + CKA_PRIVATE, + CKA_MODIFIABLE, + CKA_LABEL, + CKA_CERTIFICATE_TYPE, + CKA_SUBJECT, + CKA_ISSUER, + CKA_SERIAL_NUMBER, + CKA_VALUE +}; +const PRUint32 certAttrsCount = NSS_CKCAPI_ARRAY_SIZE(certAttrs); + +/* private keys, for now only support RSA */ +const CK_ATTRIBUTE_TYPE privKeyAttrs[] = { + CKA_CLASS, + CKA_TOKEN, + CKA_PRIVATE, + CKA_MODIFIABLE, + CKA_LABEL, + CKA_KEY_TYPE, + CKA_DERIVE, + CKA_LOCAL, + CKA_SUBJECT, + CKA_SENSITIVE, + CKA_DECRYPT, + CKA_SIGN, + CKA_SIGN_RECOVER, + CKA_UNWRAP, + CKA_EXTRACTABLE, + CKA_ALWAYS_SENSITIVE, + CKA_NEVER_EXTRACTABLE, + CKA_MODULUS, + CKA_PUBLIC_EXPONENT, +}; +const PRUint32 privKeyAttrsCount = NSS_CKCAPI_ARRAY_SIZE(privKeyAttrs); + +/* public keys, for now only support RSA */ +const CK_ATTRIBUTE_TYPE pubKeyAttrs[] = { + CKA_CLASS, + CKA_TOKEN, + CKA_PRIVATE, + CKA_MODIFIABLE, + CKA_LABEL, + CKA_KEY_TYPE, + CKA_DERIVE, + CKA_LOCAL, + CKA_SUBJECT, + CKA_ENCRYPT, + CKA_VERIFY, + CKA_VERIFY_RECOVER, + CKA_WRAP, + CKA_MODULUS, + CKA_PUBLIC_EXPONENT, +}; +const PRUint32 pubKeyAttrsCount = NSS_CKCAPI_ARRAY_SIZE(pubKeyAttrs); +static const CK_BBOOL ck_true = CK_TRUE; +static const CK_BBOOL ck_false = CK_FALSE; +static const CK_CERTIFICATE_TYPE ckc_x509 = CKC_X_509; +static const CK_KEY_TYPE ckk_rsa = CKK_RSA; +static const CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE; +static const CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY; +static const CK_OBJECT_CLASS cko_public_key = CKO_PUBLIC_KEY; +static const NSSItem ckcapi_trueItem = { + (void *)&ck_true, (PRUint32)sizeof(CK_BBOOL) }; +static const NSSItem ckcapi_falseItem = { + (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL) }; +static const NSSItem ckcapi_x509Item = { + (void *)&ckc_x509, (PRUint32)sizeof(CKC_X_509) }; +static const NSSItem ckcapi_rsaItem = { + (void *)&ckk_rsa, (PRUint32)sizeof(CK_KEY_TYPE) }; +static const NSSItem ckcapi_certClassItem = { + (void *)&cko_certificate, (PRUint32)sizeof(CK_OBJECT_CLASS) }; +static const NSSItem ckcapi_privKeyClassItem = { + (void *)&cko_private_key, (PRUint32)sizeof(CK_OBJECT_CLASS) }; +static const NSSItem ckcapi_pubKeyClassItem = { + (void *)&cko_public_key, (PRUint32)sizeof(CK_OBJECT_CLASS) }; +static const NSSItem ckcapi_emptyItem = { + (void *)&ck_true, 0}; + +/* + * these are utilities. The chould be moved to a new utilities file. + */ + +/* + * unwrap a single DER value + */ +char * +nss_ckcapi_DERUnwrap +( + char *src, + int size, + int *outSize, + char **next +) +{ + unsigned char *start = src; + unsigned char *end = src+size; + unsigned int len = 0; + + /* initialize error condition return values */ + *outSize = 0; + if (next) { + *next = src; + } + + if (size < 2) { + return start; + } + src ++ ; /* skip the tag -- should check it against an expected value! */ + len = (unsigned) *src++; + if (len & 0x80) { + int count = len & 0x7f; + len =0; + + if (count+2 > size) { + return start; + } + while (count-- > 0) { + len = (len << 8) | (unsigned) *src++; + } + } + if (len + (src-start) > (unsigned int)size) { + return start; + } + if (next) { + *next = src+len; + } + *outSize = len; + + return src; +} + +/* + * convert a PKCS #11 bytestrin into a CK_ULONG, the byte stream must be + * less than sizeof (CK_ULONG). + */ +CK_ULONG +nss_ckcapi_DataToInt +( + NSSItem *data, + CK_RV *pError +) +{ + CK_ULONG value = 0; + unsigned long count = data->size; + unsigned char *dataPtr = data->data; + unsigned long size = 0; + + *pError = CKR_OK; + + while (count--) { + value = value << 8; + value = value + *dataPtr++; + if (size || value) { + size++; + } + } + if (size > sizeof(CK_ULONG)) { + *pError = CKR_ATTRIBUTE_VALUE_INVALID; + } + return value; +} + +/* + * convert a CK_ULONG to a bytestream. Data is stored in the buffer 'buf' + * and must be at least CK_ULONG. Caller must provide buf. + */ +CK_ULONG +nss_ckcapi_IntToData +( + CK_ULONG value, + NSSItem *data, + unsigned char *dataPtr, + CK_RV *pError +) +{ + unsigned long count = 0; + unsigned long i; +#define SHIFT ((sizeof(CK_ULONG)-1)*8) + PRBool first = 0; + + *pError = CKR_OK; + + data->data = dataPtr; + for (i=0; i < sizeof(CK_ULONG); i++) { + unsigned char digit = (unsigned char)((value >> SHIFT) & 0xff); + + value = value << 8; + + /* drop leading zero bytes */ + if (first && (0 == digit)) { + continue; + } + *dataPtr++ = digit; + count++; + } + data->size = count; + return count; +} + +/* + * get an attribute from a template. Value is returned in NSS item. + * data for the item is owned by the template. + */ +CK_RV +nss_ckcapi_GetAttribute +( + CK_ATTRIBUTE_TYPE type, + CK_ATTRIBUTE *template, + CK_ULONG templateSize, + NSSItem *item +) +{ + CK_ULONG i; + + for (i=0; i < templateSize; i++) { + if (template[i].type == type) { + item->data = template[i].pValue; + item->size = template[i].ulValueLen; + return CKR_OK; + } + } + return CKR_TEMPLATE_INCOMPLETE; +} + +/* + * get an attribute which is type CK_ULONG. + */ +CK_ULONG +nss_ckcapi_GetULongAttribute +( + CK_ATTRIBUTE_TYPE type, + CK_ATTRIBUTE *template, + CK_ULONG templateSize, + CK_RV *pError +) +{ + NSSItem item; + + *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item); + if (CKR_OK != *pError) { + return (CK_ULONG) 0; + } + if (item.size != sizeof(CK_ULONG)) { + *pError = CKR_ATTRIBUTE_VALUE_INVALID; + return (CK_ULONG) 0; + } + return *(CK_ULONG *)item.data; +} + +/* + * get an attribute which is type CK_BBOOL. + */ +CK_BBOOL +nss_ckcapi_GetBoolAttribute +( + CK_ATTRIBUTE_TYPE type, + CK_ATTRIBUTE *template, + CK_ULONG templateSize, + CK_RV *pError +) +{ + NSSItem item; + + *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item); + if (CKR_OK != *pError) { + return (CK_BBOOL) 0; + } + if (item.size != sizeof(CK_BBOOL)) { + *pError = CKR_ATTRIBUTE_VALUE_INVALID; + return (CK_BBOOL) 0; + } + return *(CK_BBOOL *)item.data; +} + +/* + * get an attribute which is type CK_BBOOL. + */ +char * +nss_ckcapi_GetStringAttribute +( + CK_ATTRIBUTE_TYPE type, + CK_ATTRIBUTE *template, + CK_ULONG templateSize, + CK_RV *pError +) +{ + NSSItem item; + char *str; + + /* get the attribute */ + *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item); + if (CKR_OK != *pError) { + return (char *)NULL; + } + /* make sure it is null terminated */ + str = nss_ZNEWARRAY(NULL, char, item.size+1); + if ((char *)NULL == str) { + *pError = CKR_HOST_MEMORY; + return (char *)NULL; + } + + nsslibc_memcpy(str, item.data, item.size); + str[item.size] = 0; + + return str; +} + +/* + * Return the size in bytes of a wide string + */ +int +nss_ckcapi_WideSize +( + LPCWSTR wide +) +{ + DWORD size; + + if ((LPWSTR)NULL == wide) { + return 0; + } + size = wcslen(wide)+1; + return size*2; +} + +/* + * Covert a Unicode wide character string to a UTF8 string + */ +char * +nss_ckcapi_WideToUTF8 +( + LPCWSTR wide +) +{ + DWORD len; + DWORD size; + char *buf; + + if ((LPWSTR)NULL == wide) { + return (char *)NULL; + } + + len = nss_ckcapi_WideSize(wide); + + size = WideCharToMultiByte(CP_UTF8, 0, wide, len, NULL, 0, NULL, 0); + if (size == 0) { + return (char *)NULL; + } + buf = nss_ZNEWARRAY(NULL, char, size); + size = WideCharToMultiByte(CP_UTF8, 0, wide, len, buf, size, NULL, 0); + if (size == 0) { + nss_ZFreeIf(buf); + return (char *)NULL; + } + return buf; +} + +/* + * Return a Wide String duplicated with nss allocated memory. + */ +LPWSTR +nss_ckcapi_WideDup +( + LPCWSTR wide +) +{ + DWORD len = nss_ckcapi_WideSize(wide); + LPWSTR buf; + + if ((LPWSTR)NULL == wide) { + return (LPWSTR)NULL; + } + + len = nss_ckcapi_WideSize(wide); + + buf = (LPWSTR) nss_ZNEWARRAY(NULL, char, len); + if ((LPWSTR) NULL == buf) { + return buf; + } + nsslibc_memcpy(buf, wide, len); + return buf; +} + +/* + * Covert a UTF8 string to Unicode wide character + */ +LPWSTR +nss_ckcapi_UTF8ToWide +( + char *buf +) +{ + DWORD size; + DWORD len = strlen(buf)+1; + LPWSTR wide; + + if ((char *)NULL == buf) { + return (LPWSTR) NULL; + } + + len = strlen(buf)+1; + + size = MultiByteToWideChar(CP_UTF8, 0, buf, len, NULL, 0); + if (size == 0) { + return (LPWSTR) NULL; + } + wide = nss_ZNEWARRAY(NULL, WCHAR, size); + size = MultiByteToWideChar(CP_UTF8, 0, buf, len, wide, size); + if (size == 0) { + nss_ZFreeIf(wide); + return (LPWSTR) NULL; + } + return wide; +} + + +/* + * keep all the knowlege of how the internalObject is laid out in this function + * + * nss_ckcapi_FetchKeyContainer + * + * fetches the Provider container and info as well as a key handle for a + * private key. If something other than a private key is passed in, + * this function fails with CKR_KEY_TYPE_INCONSISTENT + */ +NSS_EXTERN CK_RV +nss_ckcapi_FetchKeyContainer +( + ckcapiInternalObject *iKey, + HCRYPTPROV *hProv, + DWORD *keySpec, + HCRYPTKEY *hKey +) +{ + ckcapiCertObject *co; + ckcapiKeyObject *ko; + BOOL rc, dummy; + DWORD msError; + + + switch (iKey->type) { + default: + case ckcapiRaw: + /* can't have raw private keys */ + return CKR_KEY_TYPE_INCONSISTENT; + case ckcapiCert: + if (iKey->objClass != CKO_PRIVATE_KEY) { + /* Only private keys have private key provider handles */ + return CKR_KEY_TYPE_INCONSISTENT; + } + co = &iKey->u.cert; + + /* OK, get the Provider */ + rc = CryptAcquireCertificatePrivateKey(co->certContext, + CRYPT_ACQUIRE_CACHE_FLAG|CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, hProv, + keySpec, &dummy); + if (!rc) { + goto loser; + } + break; + case ckcapiBareKey: + if (iKey->objClass != CKO_PRIVATE_KEY) { + /* Only private keys have private key provider handles */ + return CKR_KEY_TYPE_INCONSISTENT; + } + ko = &iKey->u.key; + + /* OK, get the Provider */ + if (0 == ko->hProv) { + rc = CryptAcquireContext(hProv, + ko->containerName, + ko->provName, + ko->provInfo.dwProvType , 0); + if (!rc) { + goto loser; + } + } else { + *hProv = ko->hProv; + } + *keySpec = ko->provInfo.dwKeySpec; + break; + } + + /* and get the crypto handle */ + rc = CryptGetUserKey(*hProv, *keySpec, hKey); + if (!rc) { + goto loser; + } + return CKR_OK; +loser: + /* map the microsoft error before leaving */ + msError = GetLastError(); + switch (msError) { + case ERROR_INVALID_HANDLE: + case ERROR_INVALID_PARAMETER: + case NTE_BAD_KEY: + case NTE_NO_KEY: + case NTE_BAD_PUBLIC_KEY: + case NTE_BAD_KEYSET: + case NTE_KEYSET_NOT_DEF: + return CKR_KEY_TYPE_INCONSISTENT; + case NTE_BAD_UID: + case NTE_KEYSET_ENTRY_BAD: + return CKR_DEVICE_ERROR; + } + return CKR_GENERAL_ERROR; +} + + +/* + * take a DER PUBLIC Key block and return the modulus and exponent + */ +static void +ckcapi_CertPopulateModulusExponent +( + ckcapiInternalObject *io +) +{ + ckcapiKeyParams *kp = &io->u.cert.key; + PCCERT_CONTEXT certContext = io->u.cert.certContext; + char *pkData = certContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData; + CK_ULONG size= certContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData; + CK_ULONG newSize; + char *ptr, *newptr; + + /* find the start of the modulus -- this will not give good results if + * the key isn't an rsa key! */ + ptr = nss_ckcapi_DERUnwrap(pkData, size, &newSize, NULL); + kp->modulus.data = nss_ckcapi_DERUnwrap(ptr, newSize, + &kp->modulus.size, &newptr); + /* changed from signed to unsigned int */ + if (0 == *(char *)kp->modulus.data) { + kp->modulus.data = ((char *)kp->modulus.data)+1; + kp->modulus.size = kp->modulus.size - 1; + } + /* changed from signed to unsigned int */ + kp->exponent.data = nss_ckcapi_DERUnwrap(newptr, (newptr-ptr)+newSize, + &kp->exponent.size, NULL); + if (0 == *(char *)kp->exponent.data) { + kp->exponent.data = ((char *)kp->exponent.data)+1; + kp->exponent.size = kp->exponent.size - 1; + } + return; +} + +typedef struct _CAPI_RSA_KEY_BLOB { + PUBLICKEYSTRUC header; + RSAPUBKEY rsa; + char data[1]; +} CAPI_RSA_KEY_BLOB; + +#define CAPI_MODULUS_OFFSET(modSize) 0 +#define CAPI_PRIME_1_OFFSET(modSize) (modSize) +#define CAPI_PRIME_2_OFFSET(modSize) ((modSize)+(modSize)/2) +#define CAPI_EXPONENT_1_OFFSET(modSize) ((modSize)*2) +#define CAPI_EXPONENT_2_OFFSET(modSize) ((modSize)*2+(modSize)/2) +#define CAPI_COEFFICIENT_OFFSET(modSize) ((modSize)*3) +#define CAPI_PRIVATE_EXP_OFFSET(modSize) ((modSize)*3+(modSize)/2) + +void +ckcapi_FetchPublicKey +( + ckcapiInternalObject *io +) +{ + ckcapiKeyParams *kp; + HCRYPTPROV hProv; + DWORD keySpec; + HCRYPTKEY hKey = 0; + CK_RV error; + DWORD bufLen; + BOOL rc; + unsigned long modulus; + char *buf = NULL; + CAPI_RSA_KEY_BLOB *blob; + + error = nss_ckcapi_FetchKeyContainer(io, &hProv, &keySpec, &hKey); + if (CKR_OK != error) { + goto loser; + } + kp = (ckcapiCert == io->type) ? &io->u.cert.key : &io->u.key.key; + + rc = CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, buf, &bufLen); + if (!rc) { + goto loser; + } + buf = nss_ZNEWARRAY(NULL, char, bufLen); + rc = CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, buf, &bufLen); + if (!rc) { + goto loser; + } + /* validate the blob */ + blob = (CAPI_RSA_KEY_BLOB *)buf; + if ((PUBLICKEYBLOB != blob->header.bType) || + (0x02 != blob->header.bVersion) || + (0x31415352 != blob->rsa.magic)) { + goto loser; + } + modulus = blob->rsa.bitlen/8; + kp->pubKey = buf; + buf = NULL; + + kp->modulus.data = &blob->data[CAPI_MODULUS_OFFSET(modulus)]; + kp->modulus.size = modulus; + ckcapi_ReverseData(&kp->modulus); + nss_ckcapi_IntToData(blob->rsa.pubexp, &kp->exponent, + kp->publicExponentData, &error); + +loser: + nss_ZFreeIf(buf); + if (0 != hKey) { + CryptDestroyKey(hKey); + } + return; +} + +void +ckcapi_FetchPrivateKey +( + ckcapiInternalObject *io +) +{ + ckcapiKeyParams *kp; + HCRYPTPROV hProv; + DWORD keySpec; + HCRYPTKEY hKey = 0; + CK_RV error; + DWORD bufLen; + BOOL rc; + unsigned long modulus; + char *buf = NULL; + CAPI_RSA_KEY_BLOB *blob; + + error = nss_ckcapi_FetchKeyContainer(io, &hProv, &keySpec, &hKey); + if (CKR_OK != error) { + goto loser; + } + kp = (ckcapiCert == io->type) ? &io->u.cert.key : &io->u.key.key; + + rc = CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, buf, &bufLen); + if (!rc) { + goto loser; + } + buf = nss_ZNEWARRAY(NULL, char, bufLen); + rc = CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, buf, &bufLen); + if (!rc) { + goto loser; + } + /* validate the blob */ + blob = (CAPI_RSA_KEY_BLOB *)buf; + if ((PRIVATEKEYBLOB != blob->header.bType) || + (0x02 != blob->header.bVersion) || + (0x32415352 != blob->rsa.magic)) { + goto loser; + } + modulus = blob->rsa.bitlen/8; + kp->privateKey = buf; + buf = NULL; + + kp->privateExponent.data = &blob->data[CAPI_PRIVATE_EXP_OFFSET(modulus)]; + kp->privateExponent.size = modulus; + ckcapi_ReverseData(&kp->privateExponent); + kp->prime1.data = &blob->data[CAPI_PRIME_1_OFFSET(modulus)]; + kp->prime1.size = modulus/2; + ckcapi_ReverseData(&kp->prime1); + kp->prime2.data = &blob->data[CAPI_PRIME_2_OFFSET(modulus)]; + kp->prime2.size = modulus/2; + ckcapi_ReverseData(&kp->prime2); + kp->exponent1.data = &blob->data[CAPI_EXPONENT_1_OFFSET(modulus)]; + kp->exponent1.size = modulus/2; + ckcapi_ReverseData(&kp->exponent1); + kp->exponent2.data = &blob->data[CAPI_EXPONENT_2_OFFSET(modulus)]; + kp->exponent2.size = modulus/2; + ckcapi_ReverseData(&kp->exponent2); + kp->coefficient.data = &blob->data[CAPI_COEFFICIENT_OFFSET(modulus)]; + kp->coefficient.size = modulus/2; + ckcapi_ReverseData(&kp->coefficient); + +loser: + nss_ZFreeIf(buf); + if (0 != hKey) { + CryptDestroyKey(hKey); + } + return; +} + + +void +ckcapi_PopulateModulusExponent +( + ckcapiInternalObject *io +) +{ + if (ckcapiCert == io->type) { + ckcapi_CertPopulateModulusExponent(io); + } else { + ckcapi_FetchPublicKey(io); + } + return; +} + +/* + * fetch the friendly name attribute. + * can only be called with ckcapiCert type objects! + */ +void +ckcapi_FetchLabel +( + ckcapiInternalObject *io +) +{ + ckcapiCertObject *co = &io->u.cert; + char *label; + PCCERT_CONTEXT certContext = io->u.cert.certContext; + char labelDataUTF16[128]; + DWORD size = sizeof(labelDataUTF16); + DWORD size8 = sizeof(co->labelData); + BOOL rv; + + rv = CertGetCertificateContextProperty(certContext, + CERT_FRIENDLY_NAME_PROP_ID, labelDataUTF16, &size); + if (rv) { + co->labelData = nss_ckcapi_WideToUTF8((LPCWSTR)labelDataUTF16); + if ((CHAR *)NULL == co->labelData) { + rv = 0; + } else { + size = strlen(co->labelData); + } + } + label = co->labelData; + /* we are presuming a user cert, make sure it has a nickname, even if + * Microsoft never gave it one */ + if (!rv && co->hasID) { + DWORD mserror = GetLastError(); +#define DEFAULT_NICKNAME "no Microsoft nickname" + label = DEFAULT_NICKNAME; + size = sizeof(DEFAULT_NICKNAME); + rv = 1; + } + + if (rv) { + co->label.data = label; + co->label.size = size; + } + return; +} + +void +ckcapi_FetchSerial +( + ckcapiInternalObject *io +) +{ + ckcapiCertObject *co = &io->u.cert; + PCCERT_CONTEXT certContext = io->u.cert.certContext; + DWORD size = sizeof(co->derSerial); + + BOOL rc = CryptEncodeObject(X509_ASN_ENCODING, + X509_MULTI_BYTE_INTEGER, + &certContext->pCertInfo->SerialNumber, + co->derSerial, + &size); + if (rc) { + co->serial.data = co->derSerial; + co->serial.size = size; + } + return; +} + +/* + * fetch the key ID. + */ +void +ckcapi_FetchID +( + ckcapiInternalObject *io +) +{ + PCCERT_CONTEXT certContext = io->u.cert.certContext; + DWORD size = 0; + BOOL rc; + + rc = CertGetCertificateContextProperty(certContext, + CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size); + if (!rc) { + return; + } + io->idData = nss_ZNEWARRAY(NULL, char, size); + if (io->idData == NULL) { + return; + } + + rc = CertGetCertificateContextProperty(certContext, + CERT_KEY_IDENTIFIER_PROP_ID, io->idData, &size); + if (!rc) { + nss_ZFreeIf(io->idData); + io->idData = NULL; + return; + } + io->id.data = io->idData; + io->id.size = size; + return; +} + +/* + * fetch the hash key. + */ +void +ckcapi_CertFetchHashKey +( + ckcapiInternalObject *io +) +{ + ckcapiCertObject *co = &io->u.cert; + PCCERT_CONTEXT certContext = io->u.cert.certContext; + DWORD size = certContext->cbCertEncoded; + DWORD max = sizeof(io->hashKeyData)-1; + DWORD offset = 0; + + /* make sure we don't over flow. NOTE: cutting the top of a cert is + * not a big issue because the signature for will be unique for the cert */ + if (size > max) { + offset = size - max; + size = max; + } + + nsslibc_memcpy(io->hashKeyData,certContext->pbCertEncoded+offset, size); + io->hashKeyData[size] = (char)(io->objClass & 0xff); + + io->hashKey.data = io->hashKeyData; + io->hashKey.size = size+1; + return; +} + +/* + * fetch the hash key. + */ +void +ckcapi_KeyFetchHashKey +( + ckcapiInternalObject *io +) +{ + ckcapiKeyObject *ko = &io->u.key; + DWORD size; + DWORD max = sizeof(io->hashKeyData)-2; + DWORD offset = 0; + DWORD provLen = strlen(ko->provName); + DWORD containerLen = strlen(ko->containerName); + + + size = provLen + containerLen; + + /* make sure we don't overflow, try to keep things unique */ + if (size > max) { + DWORD diff = ((size - max)+1)/2; + provLen -= diff; + containerLen -= diff; + size = provLen+containerLen; + } + + nsslibc_memcpy(io->hashKeyData, ko->provName, provLen); + nsslibc_memcpy(&io->hashKeyData[provLen], + ko->containerName, + containerLen); + io->hashKeyData[size] = (char)(io->objClass & 0xff); + io->hashKeyData[size+1] = (char)(ko->provInfo.dwKeySpec & 0xff); + + io->hashKey.data = io->hashKeyData; + io->hashKey.size = size+2; + return; +} + +/* + * fetch the hash key. + */ +void +ckcapi_FetchHashKey +( + ckcapiInternalObject *io +) +{ + if (ckcapiCert == io->type) { + ckcapi_CertFetchHashKey(io); + } else { + ckcapi_KeyFetchHashKey(io); + } + return; +} + +const NSSItem * +ckcapi_FetchCertAttribute +( + ckcapiInternalObject *io, + CK_ATTRIBUTE_TYPE type +) +{ + PCCERT_CONTEXT certContext = io->u.cert.certContext; + switch(type) { + case CKA_CLASS: + return &ckcapi_certClassItem; + case CKA_TOKEN: + return &ckcapi_trueItem; + case CKA_MODIFIABLE: + case CKA_PRIVATE: + return &ckcapi_falseItem; + case CKA_CERTIFICATE_TYPE: + return &ckcapi_x509Item; + case CKA_LABEL: + if (0 == io->u.cert.label.size) { + ckcapi_FetchLabel(io); + } + return &io->u.cert.label; + case CKA_SUBJECT: + if (0 == io->u.cert.subject.size) { + io->u.cert.subject.data = certContext->pCertInfo->Subject.pbData; + io->u.cert.subject.size = certContext->pCertInfo->Subject.cbData; + } + return &io->u.cert.subject; + case CKA_ISSUER: + if (0 == io->u.cert.issuer.size) { + io->u.cert.issuer.data = certContext->pCertInfo->Issuer.pbData; + io->u.cert.issuer.size = certContext->pCertInfo->Issuer.cbData; + } + return &io->u.cert.issuer; + case CKA_SERIAL_NUMBER: + if (0 == io->u.cert.serial.size) { + /* not exactly right. This should be the encoded serial number, but + * it's the decoded serial number! */ + ckcapi_FetchSerial(io); + } + return &io->u.cert.serial; + case CKA_VALUE: + if (0 == io->u.cert.derCert.size) { + io->u.cert.derCert.data = io->u.cert.certContext->pbCertEncoded; + io->u.cert.derCert.size = io->u.cert.certContext->cbCertEncoded; + } + return &io->u.cert.derCert; + case CKA_ID: + if (!io->u.cert.hasID) { + return NULL; + } + if (0 == io->id.size) { + ckcapi_FetchID(io); + } + return &io->id; + default: + break; + } + return NULL; +} + +const NSSItem * +ckcapi_FetchPubKeyAttribute +( + ckcapiInternalObject *io, + CK_ATTRIBUTE_TYPE type +) +{ + PRBool isCertType = (ckcapiCert == io->type); + ckcapiKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key; + + switch(type) { + case CKA_CLASS: + return &ckcapi_pubKeyClassItem; + case CKA_TOKEN: + case CKA_LOCAL: + case CKA_ENCRYPT: + case CKA_VERIFY: + case CKA_VERIFY_RECOVER: + return &ckcapi_trueItem; + case CKA_PRIVATE: + case CKA_MODIFIABLE: + case CKA_DERIVE: + case CKA_WRAP: + return &ckcapi_falseItem; + case CKA_KEY_TYPE: + return &ckcapi_rsaItem; + case CKA_LABEL: + if (!isCertType) { + return &ckcapi_emptyItem; + } + if (0 == io->u.cert.label.size) { + ckcapi_FetchLabel(io); + } + return &io->u.cert.label; + case CKA_SUBJECT: + if (!isCertType) { + return &ckcapi_emptyItem; + } + if (0 == io->u.cert.subject.size) { + PCCERT_CONTEXT certContext= io->u.cert.certContext; + io->u.cert.subject.data = certContext->pCertInfo->Subject.pbData; + io->u.cert.subject.size = certContext->pCertInfo->Subject.cbData; + } + return &io->u.cert.subject; + case CKA_MODULUS: + if (0 == kp->modulus.size) { + ckcapi_PopulateModulusExponent(io); + } + return &kp->modulus; + case CKA_PUBLIC_EXPONENT: + if (0 == kp->modulus.size) { + ckcapi_PopulateModulusExponent(io); + } + return &kp->exponent; + case CKA_ID: + if (0 == io->id.size) { + ckcapi_FetchID(io); + } + return &io->id; + default: + break; + } + return NULL; +} + +const NSSItem * +ckcapi_FetchPrivKeyAttribute +( + ckcapiInternalObject *io, + CK_ATTRIBUTE_TYPE type +) +{ + PRBool isCertType = (ckcapiCert == io->type); + ckcapiKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key; + + switch(type) { + case CKA_CLASS: + return &ckcapi_privKeyClassItem; + case CKA_TOKEN: + case CKA_LOCAL: + case CKA_SIGN: + case CKA_DECRYPT: + case CKA_SIGN_RECOVER: + return &ckcapi_trueItem; + case CKA_SENSITIVE: + case CKA_PRIVATE: /* should move in the future */ + case CKA_MODIFIABLE: + case CKA_DERIVE: + case CKA_UNWRAP: + case CKA_EXTRACTABLE: /* will probably move in the future */ + case CKA_ALWAYS_SENSITIVE: + case CKA_NEVER_EXTRACTABLE: + return &ckcapi_falseItem; + case CKA_KEY_TYPE: + return &ckcapi_rsaItem; + case CKA_LABEL: + if (!isCertType) { + return &ckcapi_emptyItem; + } + if (0 == io->u.cert.label.size) { + ckcapi_FetchLabel(io); + } + return &io->u.cert.label; + case CKA_SUBJECT: + if (!isCertType) { + return &ckcapi_emptyItem; + } + if (0 == io->u.cert.subject.size) { + PCCERT_CONTEXT certContext= io->u.cert.certContext; + io->u.cert.subject.data = certContext->pCertInfo->Subject.pbData; + io->u.cert.subject.size = certContext->pCertInfo->Subject.cbData; + } + return &io->u.cert.subject; + case CKA_MODULUS: + if (0 == kp->modulus.size) { + ckcapi_PopulateModulusExponent(io); + } + return &kp->modulus; + case CKA_PUBLIC_EXPONENT: + if (0 == kp->modulus.size) { + ckcapi_PopulateModulusExponent(io); + } + return &kp->exponent; + case CKA_PRIVATE_EXPONENT: + if (0 == kp->privateExponent.size) { + ckcapi_FetchPrivateKey(io); + } + return &kp->privateExponent; + case CKA_PRIME_1: + if (0 == kp->privateExponent.size) { + ckcapi_FetchPrivateKey(io); + } + return &kp->prime1; + case CKA_PRIME_2: + if (0 == kp->privateExponent.size) { + ckcapi_FetchPrivateKey(io); + } + return &kp->prime2; + case CKA_EXPONENT_1: + if (0 == kp->privateExponent.size) { + ckcapi_FetchPrivateKey(io); + } + return &kp->exponent1; + case CKA_EXPONENT_2: + if (0 == kp->privateExponent.size) { + ckcapi_FetchPrivateKey(io); + } + return &kp->exponent2; + case CKA_COEFFICIENT: + if (0 == kp->privateExponent.size) { + ckcapi_FetchPrivateKey(io); + } + return &kp->coefficient; + case CKA_ID: + if (0 == io->id.size) { + ckcapi_FetchID(io); + } + return &io->id; + default: + return NULL; + } +} + +const NSSItem * +nss_ckcapi_FetchAttribute +( + ckcapiInternalObject *io, + CK_ATTRIBUTE_TYPE type +) +{ + CK_ULONG i; + + if (io->type == ckcapiRaw) { + for( i = 0; i < io->u.raw.n; i++ ) { + if( type == io->u.raw.types[i] ) { + return &io->u.raw.items[i]; + } + } + return NULL; + } + /* deal with the common attributes */ + switch (io->objClass) { + case CKO_CERTIFICATE: + return ckcapi_FetchCertAttribute(io, type); + case CKO_PRIVATE_KEY: + return ckcapi_FetchPrivKeyAttribute(io, type); + case CKO_PUBLIC_KEY: + return ckcapi_FetchPubKeyAttribute(io, type); + } + return NULL; +} + +/* + * check to see if the certificate already exists + */ +static PRBool +ckcapi_cert_exists( + NSSItem *value, + ckcapiInternalObject **io +) +{ + int count,i; + PRUint32 size = 0; + ckcapiInternalObject **listp = NULL; + CK_ATTRIBUTE myTemplate[2]; + CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; + CK_ULONG templateCount = 2; + CK_RV error; + PRBool found = PR_FALSE; + + myTemplate[0].type = CKA_CLASS; + myTemplate[0].pValue = &cert_class; + myTemplate[0].ulValueLen = sizeof(cert_class); + myTemplate[1].type = CKA_VALUE; + myTemplate[1].pValue = value->data; + myTemplate[1].ulValueLen = value->size; + + count = nss_ckcapi_collect_all_certs(myTemplate, templateCount, &listp, + &size, 0, &error); + + /* free them */ + if (count > 1) { + *io = listp[0]; + found = PR_TRUE; + } + + for (i=1; i < count; i++) { + nss_ckcapi_DestroyInternalObject(listp[i]); + } + nss_ZFreeIf(listp); + return found; +} + +static PRBool +ckcapi_cert_hasEmail +( + PCCERT_CONTEXT certContext +) +{ + int count; + + count = CertGetNameString(certContext, CERT_NAME_EMAIL_TYPE, + 0, NULL, NULL, 0); + + return count > 1 ? PR_TRUE : PR_FALSE; +} + +static PRBool +ckcapi_cert_isRoot +( + PCCERT_CONTEXT certContext +) +{ + return CertCompareCertificateName(certContext->dwCertEncodingType, + &certContext->pCertInfo->Issuer, &certContext->pCertInfo->Subject); +} + +static PRBool +ckcapi_cert_isCA +( + PCCERT_CONTEXT certContext +) +{ + PCERT_EXTENSION extension; + CERT_BASIC_CONSTRAINTS2_INFO basicInfo; + DWORD size = sizeof(basicInfo); + BOOL rc; + + extension = CertFindExtension (szOID_BASIC_CONSTRAINTS, + certContext->pCertInfo->cExtension, + certContext->pCertInfo->rgExtension); + if ((PCERT_EXTENSION) NULL == extension ) { + return PR_FALSE; + } + rc = CryptDecodeObject(X509_ASN_ENCODING, szOID_BASIC_CONSTRAINTS2, + extension->Value.pbData, extension->Value.cbData, + 0, &basicInfo, &size); + if (!rc) { + return PR_FALSE; + } + return (PRBool) basicInfo.fCA; +} + +static CRYPT_KEY_PROV_INFO * +ckcapi_cert_getPrivateKeyInfo +( + PCCERT_CONTEXT certContext, + NSSItem *keyID +) +{ + BOOL rc; + CRYPT_HASH_BLOB msKeyID; + DWORD size = 0; + CRYPT_KEY_PROV_INFO *prov = NULL; + + msKeyID.cbData = keyID->size; + msKeyID.pbData = keyID->data; + + rc = CryptGetKeyIdentifierProperty( + &msKeyID, + CERT_KEY_PROV_INFO_PROP_ID, + 0, NULL, NULL, NULL, &size); + if (!rc) { + return (CRYPT_KEY_PROV_INFO *)NULL; + } + prov = (CRYPT_KEY_PROV_INFO *)nss_ZAlloc(NULL, size); + if ((CRYPT_KEY_PROV_INFO *)prov == NULL) { + return (CRYPT_KEY_PROV_INFO *) NULL; + } + rc = CryptGetKeyIdentifierProperty( + &msKeyID, + CERT_KEY_PROV_INFO_PROP_ID, + 0, NULL, NULL, prov, &size); + if (!rc) { + nss_ZFreeIf(prov); + return (CRYPT_KEY_PROV_INFO *)NULL; + } + + return prov; +} + +static CRYPT_KEY_PROV_INFO * +ckcapi_cert_getProvInfo +( + ckcapiInternalObject *io +) +{ + BOOL rc; + DWORD size = 0; + CRYPT_KEY_PROV_INFO *prov = NULL; + + rc = CertGetCertificateContextProperty( + io->u.cert.certContext, + CERT_KEY_PROV_INFO_PROP_ID, + NULL, &size); + if (!rc) { + return (CRYPT_KEY_PROV_INFO *)NULL; + } + prov = (CRYPT_KEY_PROV_INFO *)nss_ZAlloc(NULL, size); + if ((CRYPT_KEY_PROV_INFO *)prov == NULL) { + return (CRYPT_KEY_PROV_INFO *) NULL; + } + rc = CertGetCertificateContextProperty( + io->u.cert.certContext, + CERT_KEY_PROV_INFO_PROP_ID, + prov, &size); + if (!rc) { + nss_ZFreeIf(prov); + return (CRYPT_KEY_PROV_INFO *)NULL; + } + + return prov; +} + +/* forward declaration */ +static void +ckcapi_removeObjectFromHash +( + ckcapiInternalObject *io +); + +/* + * Finalize - unneeded + * Destroy + * IsTokenObject - CK_TRUE + * GetAttributeCount + * GetAttributeTypes + * GetAttributeSize + * GetAttribute + * SetAttribute + * GetObjectSize + */ + +static CK_RV +ckcapi_mdObject_Destroy +( + NSSCKMDObject *mdObject, + NSSCKFWObject *fwObject, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance +) +{ + ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc; + CK_OBJECT_CLASS objClass; + BOOL rc; + DWORD provType; + DWORD msError; + PRBool isCertType = (PRBool)(ckcapiCert == io->type); + HCERTSTORE hStore = 0; + + if (ckcapiRaw == io->type) { + /* there is not 'object write protected' error, use the next best thing */ + return CKR_TOKEN_WRITE_PROTECTED; + } + + objClass = io->objClass; + if (CKO_CERTIFICATE == objClass) { + PCCERT_CONTEXT certContext; + + /* get the store */ + hStore = CertOpenSystemStore(0, io->u.cert.certStore); + if (0 == hStore) { + rc = 0; + goto loser; + } + certContext = CertFindCertificateInStore(hStore, X509_ASN_ENCODING, 0, + CERT_FIND_EXISTING, io->u.cert.certContext, NULL); + if ((PCCERT_CONTEXT)NULL == certContext) { + rc = 0; + goto loser; + } + rc = CertDeleteCertificateFromStore(certContext); + CertFreeCertificateContext(certContext); + } else { + char *provName = NULL; + char *containerName = NULL; + HCRYPTPROV hProv; + CRYPT_HASH_BLOB msKeyID; + + if (0 == io->id.size) { + ckcapi_FetchID(io); + } + + if (isCertType) { + CRYPT_KEY_PROV_INFO * provInfo = ckcapi_cert_getProvInfo(io); + provName = nss_ckcapi_WideToUTF8(provInfo->pwszProvName); + containerName = nss_ckcapi_WideToUTF8(provInfo->pwszContainerName); + provType = provInfo->dwProvType; + nss_ZFreeIf(provInfo); + } else { + provName = io->u.key.provName; + containerName = io->u.key.containerName; + provType = io->u.key.provInfo.dwProvType; + io->u.key.provName = NULL; + io->u.key.containerName = NULL; + } + /* first remove the key id pointer */ + msKeyID.cbData = io->id.size; + msKeyID.pbData = io->id.data; + rc = CryptSetKeyIdentifierProperty(&msKeyID, + CERT_KEY_PROV_INFO_PROP_ID, CRYPT_KEYID_DELETE_FLAG, NULL, NULL, NULL); + if (rc) { + rc = CryptAcquireContext(&hProv, containerName, provName, provType, + CRYPT_DELETEKEYSET); + } + nss_ZFreeIf(provName); + nss_ZFreeIf(containerName); + } +loser: + + if (hStore) { + CertCloseStore(hStore, 0); + } + if (!rc) { + msError = GetLastError(); + return CKR_GENERAL_ERROR; + } + + /* remove it from the hash */ + ckcapi_removeObjectFromHash(io); + + /* free the puppy.. */ + nss_ckcapi_DestroyInternalObject(io); + return CKR_OK; +} + +static CK_BBOOL +ckcapi_mdObject_IsTokenObject +( + NSSCKMDObject *mdObject, + NSSCKFWObject *fwObject, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance +) +{ + return CK_TRUE; +} + +static CK_ULONG +ckcapi_mdObject_GetAttributeCount +( + NSSCKMDObject *mdObject, + NSSCKFWObject *fwObject, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError +) +{ + ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc; + + if (ckcapiRaw == io->type) { + return io->u.raw.n; + } + switch (io->objClass) { + case CKO_CERTIFICATE: + return certAttrsCount; + case CKO_PUBLIC_KEY: + return pubKeyAttrsCount; + case CKO_PRIVATE_KEY: + return privKeyAttrsCount; + default: + break; + } + return 0; +} + +static CK_RV +ckcapi_mdObject_GetAttributeTypes +( + NSSCKMDObject *mdObject, + NSSCKFWObject *fwObject, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_ATTRIBUTE_TYPE_PTR typeArray, + CK_ULONG ulCount +) +{ + ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc; + CK_ULONG i; + CK_RV error = CKR_OK; + const CK_ATTRIBUTE_TYPE *attrs = NULL; + CK_ULONG size = ckcapi_mdObject_GetAttributeCount( + mdObject, fwObject, mdSession, fwSession, + mdToken, fwToken, mdInstance, fwInstance, &error); + + if( size != ulCount ) { + return CKR_BUFFER_TOO_SMALL; + } + if (io->type == ckcapiRaw) { + attrs = io->u.raw.types; + } else switch(io->objClass) { + case CKO_CERTIFICATE: + attrs = certAttrs; + break; + case CKO_PUBLIC_KEY: + attrs = pubKeyAttrs; + break; + case CKO_PRIVATE_KEY: + attrs = privKeyAttrs; + break; + default: + return CKR_OK; + } + + for( i = 0; i < size; i++) { + typeArray[i] = attrs[i]; + } + + return CKR_OK; +} + +static CK_ULONG +ckcapi_mdObject_GetAttributeSize +( + NSSCKMDObject *mdObject, + NSSCKFWObject *fwObject, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_ATTRIBUTE_TYPE attribute, + CK_RV *pError +) +{ + ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc; + + const NSSItem *b; + + b = nss_ckcapi_FetchAttribute(io, attribute); + + if ((const NSSItem *)NULL == b) { + *pError = CKR_ATTRIBUTE_TYPE_INVALID; + return 0; + } + return b->size; +} + +static CK_RV +ckcapi_mdObject_SetAttribute +( + NSSCKMDObject *mdObject, + NSSCKFWObject *fwObject, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_ATTRIBUTE_TYPE attribute, + NSSItem *value +) +{ + return CKR_OK; +} + +static NSSCKFWItem +ckcapi_mdObject_GetAttribute +( + NSSCKMDObject *mdObject, + NSSCKFWObject *fwObject, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_ATTRIBUTE_TYPE attribute, + CK_RV *pError +) +{ + NSSCKFWItem mdItem; + ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc; + + mdItem.needsFreeing = PR_FALSE; + mdItem.item = (NSSItem*)nss_ckcapi_FetchAttribute(io, attribute); + + if ((NSSItem *)NULL == mdItem.item) { + *pError = CKR_ATTRIBUTE_TYPE_INVALID; + } + + return mdItem; +} + +static CK_ULONG +ckcapi_mdObject_GetObjectSize +( + NSSCKMDObject *mdObject, + NSSCKFWObject *fwObject, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError +) +{ + ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc; + CK_ULONG rv = 1; + + /* size is irrelevant to this token */ + return rv; +} + +static const NSSCKMDObject +ckcapi_prototype_mdObject = { + (void *)NULL, /* etc */ + NULL, /* Finalize */ + ckcapi_mdObject_Destroy, + ckcapi_mdObject_IsTokenObject, + ckcapi_mdObject_GetAttributeCount, + ckcapi_mdObject_GetAttributeTypes, + ckcapi_mdObject_GetAttributeSize, + ckcapi_mdObject_GetAttribute, + NULL, /* FreeAttribute */ + ckcapi_mdObject_SetAttribute, + ckcapi_mdObject_GetObjectSize, + (void *)NULL /* null terminator */ +}; + +static nssHash *ckcapiInternalObjectHash = NULL; + +NSS_IMPLEMENT NSSCKMDObject * +nss_ckcapi_CreateMDObject +( + NSSArena *arena, + ckcapiInternalObject *io, + CK_RV *pError +) +{ + if ((nssHash *)NULL == ckcapiInternalObjectHash) { + ckcapiInternalObjectHash = nssHash_CreateItem(NULL, 10); + } + if (ckcapiCert == io->type) { + /* the hash key, not a cryptographic key */ + NSSItem *key = &io->hashKey; + ckcapiInternalObject *old_o = NULL; + + if (key->size == 0) { + ckcapi_FetchHashKey(io); + } + old_o = (ckcapiInternalObject *) + nssHash_Lookup(ckcapiInternalObjectHash, key); + if (!old_o) { + nssHash_Add(ckcapiInternalObjectHash, key, io); + } else if (old_o != io) { + nss_ckcapi_DestroyInternalObject(io); + io = old_o; + } + } + + if ( (void*)NULL == io->mdObject.etc) { + (void) nsslibc_memcpy(&io->mdObject,&ckcapi_prototype_mdObject, + sizeof(ckcapi_prototype_mdObject)); + io->mdObject.etc = (void *)io; + } + return &io->mdObject; +} + +static void +ckcapi_removeObjectFromHash +( + ckcapiInternalObject *io +) +{ + NSSItem *key = &io->hashKey; + + if ((nssHash *)NULL == ckcapiInternalObjectHash) { + return; + } + if (key->size == 0) { + ckcapi_FetchHashKey(io); + } + nssHash_Remove(ckcapiInternalObjectHash, key); + return; +} + +void +nss_ckcapi_DestroyInternalObject +( + ckcapiInternalObject *io +) +{ + switch (io->type) { + case ckcapiRaw: + return; + case ckcapiCert: + CertFreeCertificateContext(io->u.cert.certContext); + nss_ZFreeIf(io->u.cert.labelData); + nss_ZFreeIf(io->u.cert.key.privateKey); + nss_ZFreeIf(io->u.cert.key.pubKey); + nss_ZFreeIf(io->idData); + break; + case ckcapiBareKey: + nss_ZFreeIf(io->u.key.provInfo.pwszContainerName); + nss_ZFreeIf(io->u.key.provInfo.pwszProvName); + nss_ZFreeIf(io->u.key.provName); + nss_ZFreeIf(io->u.key.containerName); + nss_ZFreeIf(io->u.key.key.privateKey); + nss_ZFreeIf(io->u.key.key.pubKey); + if (0 != io->u.key.hProv) { + CryptReleaseContext(io->u.key.hProv, 0); + } + nss_ZFreeIf(io->idData); + break; + } + nss_ZFreeIf(io); + return; +} + +static ckcapiInternalObject * +nss_ckcapi_CreateCertificate +( + NSSCKFWSession *fwSession, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + CK_RV *pError +) +{ + NSSItem value; + NSSItem keyID; + char *storeStr; + ckcapiInternalObject *io = NULL; + PCCERT_CONTEXT certContext = NULL; + PCCERT_CONTEXT storedCertContext = NULL; + CRYPT_KEY_PROV_INFO *prov_info = NULL; + char *nickname = NULL; + HCERTSTORE hStore = 0; + DWORD msError = 0; + PRBool hasID; + CK_RV dummy; + BOOL rc; + + *pError = nss_ckcapi_GetAttribute(CKA_VALUE, pTemplate, + ulAttributeCount, &value); + + if (CKR_OK != *pError) { + return (ckcapiInternalObject *)NULL; + } + + *pError = nss_ckcapi_GetAttribute(CKA_ID, pTemplate, + ulAttributeCount, &keyID); + + if (CKR_OK != *pError) { + return (ckcapiInternalObject *)NULL; + } + + if (ckcapi_cert_exists(&value, &io)) { + return io; + } + + /* OK, we are creating a new one, figure out what store it belongs to.. + * first get a certContext handle.. */ + certContext = CertCreateCertificateContext(X509_ASN_ENCODING, + value.data, value.size); + if ((PCCERT_CONTEXT) NULL == certContext) { + msError = GetLastError(); + *pError = CKR_ATTRIBUTE_VALUE_INVALID; + goto loser; + } + + /* do we have a private key laying around... */ + prov_info = ckcapi_cert_getPrivateKeyInfo(certContext, &keyID); + if (prov_info) { + CRYPT_DATA_BLOB msKeyID; + storeStr = "My"; + hasID = PR_TRUE; + rc = CertSetCertificateContextProperty(certContext, + CERT_KEY_PROV_INFO_PROP_ID, + 0, prov_info); + nss_ZFreeIf(prov_info); + if (!rc) { + msError = GetLastError(); + *pError = CKR_DEVICE_ERROR; + goto loser; + } + msKeyID.cbData = keyID.size; + msKeyID.pbData = keyID.data; + rc = CertSetCertificateContextProperty(certContext, + CERT_KEY_IDENTIFIER_PROP_ID, + 0, &msKeyID); + if (!rc) { + msError = GetLastError(); + *pError = CKR_DEVICE_ERROR; + goto loser; + } + + /* does it look like a CA */ + } else if (ckcapi_cert_isCA(certContext)) { + storeStr = ckcapi_cert_isRoot(certContext) ? "CA" : "Root"; + /* does it look like an S/MIME cert */ + } else if (ckcapi_cert_hasEmail(certContext)) { + storeStr = "AddressBook"; + } else { + /* just pick a store */ + storeStr = "CA"; + } + + /* get the nickname, not an error if we can't find it */ + nickname = nss_ckcapi_GetStringAttribute(CKA_LABEL, pTemplate, + ulAttributeCount, &dummy); + if (nickname) { + LPWSTR nicknameUTF16 = NULL; + CRYPT_DATA_BLOB nicknameBlob; + + nicknameUTF16 = nss_ckcapi_UTF8ToWide(nickname); + nss_ZFreeIf(nickname); + nickname = NULL; + if ((LPWSTR)NULL == nicknameUTF16) { + *pError = CKR_HOST_MEMORY; + goto loser; + } + nicknameBlob.cbData = nss_ckcapi_WideSize(nicknameUTF16); + nicknameBlob.pbData = (BYTE *)nicknameUTF16; + rc = CertSetCertificateContextProperty(certContext, + CERT_FRIENDLY_NAME_PROP_ID, 0, &nicknameBlob); + nss_ZFreeIf(nicknameUTF16); + if (!rc) { + msError = GetLastError(); + *pError = CKR_DEVICE_ERROR; + goto loser; + } + } + + hStore = CertOpenSystemStore((HCRYPTPROV) NULL, storeStr); + if (0 == hStore) { + msError = GetLastError(); + *pError = CKR_DEVICE_ERROR; + goto loser; + } + + rc = CertAddCertificateContextToStore(hStore, certContext, + CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES, &storedCertContext); + CertFreeCertificateContext(certContext); + certContext = NULL; + CertCloseStore(hStore, 0); + hStore = 0; + if (!rc) { + msError = GetLastError(); + *pError = CKR_DEVICE_ERROR; + goto loser; + } + + io = nss_ZNEW(NULL, ckcapiInternalObject); + if ((ckcapiInternalObject *)NULL == io) { + *pError = CKR_HOST_MEMORY; + goto loser; + } + io->type = ckcapiCert; + io->objClass = CKO_CERTIFICATE; + io->u.cert.certContext = storedCertContext; + io->u.cert.hasID = hasID; + return io; + +loser: + if (certContext) { + CertFreeCertificateContext(certContext); + certContext = NULL; + } + if (storedCertContext) { + CertFreeCertificateContext(storedCertContext); + storedCertContext = NULL; + } + if (0 != hStore) { + CertCloseStore(hStore, 0); + } + return (ckcapiInternalObject *)NULL; + +} + +static char * +ckcapi_getDefaultProvider +( + CK_RV *pError +) +{ + char *name = NULL; + BOOL rc; + DWORD nameLength = 0; + + rc = CryptGetDefaultProvider(PROV_RSA_FULL, NULL, CRYPT_USER_DEFAULT, NULL, + &nameLength); + if (!rc) { + return (char *)NULL; + } + + name = nss_ZNEWARRAY(NULL, char, nameLength); + if ((char *)NULL == name ) { + return (char *)NULL; + } + rc = CryptGetDefaultProvider(PROV_RSA_FULL, NULL, CRYPT_USER_DEFAULT, name, + &nameLength); + if (!rc) { + nss_ZFreeIf(name); + return (char *)NULL; + } + + return name; +} + +static char * +ckcapi_getContainer +( + CK_RV *pError, + NSSItem *id +) +{ + RPC_STATUS rstat; + UUID uuid; + char *uuidStr; + char *container; + + rstat = UuidCreate(&uuid); + rstat = UuidToString(&uuid, &uuidStr); + + /* convert it from rcp memory to our own */ + container = nssUTF8_Duplicate(uuidStr, NULL); + RpcStringFree(&uuidStr); + + return container; +} + +static CK_RV +ckcapi_buildPrivateKeyBlob +( + NSSItem *keyBlob, + NSSItem *modulus, + NSSItem *publicExponent, + NSSItem *privateExponent, + NSSItem *prime1, + NSSItem *prime2, + NSSItem *exponent1, + NSSItem *exponent2, + NSSItem *coefficient, + PRBool isKeyExchange +) +{ + CAPI_RSA_KEY_BLOB *keyBlobData = NULL; + unsigned char *target; + unsigned long modSize = modulus->size; + unsigned long dataSize; + CK_RV error = CKR_OK; + + /* validate extras */ + if (privateExponent->size != modSize) { + error = CKR_ATTRIBUTE_VALUE_INVALID; + goto loser; + } + if (prime1->size != modSize/2) { + error = CKR_ATTRIBUTE_VALUE_INVALID; + goto loser; + } + if (prime2->size != modSize/2) { + error = CKR_ATTRIBUTE_VALUE_INVALID; + goto loser; + } + if (exponent1->size != modSize/2) { + error = CKR_ATTRIBUTE_VALUE_INVALID; + goto loser; + } + if (exponent2->size != modSize/2) { + error = CKR_ATTRIBUTE_VALUE_INVALID; + goto loser; + } + if (coefficient->size != modSize/2) { + error = CKR_ATTRIBUTE_VALUE_INVALID; + goto loser; + } + dataSize = (modSize*4)+(modSize/2) + sizeof(CAPI_RSA_KEY_BLOB); + keyBlobData = (CAPI_RSA_KEY_BLOB *)nss_ZAlloc(NULL, dataSize); + if ((CAPI_RSA_KEY_BLOB *)NULL == keyBlobData) { + error = CKR_HOST_MEMORY; + goto loser; + } + + keyBlobData->header.bType = PRIVATEKEYBLOB; + keyBlobData->header.bVersion = 0x02; + keyBlobData->header.reserved = 0x00; + keyBlobData->header.aiKeyAlg = isKeyExchange ? CALG_RSA_KEYX:CALG_RSA_SIGN; + keyBlobData->rsa.magic = 0x32415352; + keyBlobData->rsa.bitlen = modSize * 8; + keyBlobData->rsa.pubexp = nss_ckcapi_DataToInt(publicExponent,&error); + if (CKR_OK != error) { + goto loser; + } + + target = &keyBlobData->data[CAPI_MODULUS_OFFSET(modSize)]; + nsslibc_memcpy(target, modulus->data, modulus->size); + modulus->data = target; + ckcapi_ReverseData(modulus); + + target = &keyBlobData->data[CAPI_PRIVATE_EXP_OFFSET(modSize)]; + nsslibc_memcpy(target, privateExponent->data, privateExponent->size); + privateExponent->data = target; + ckcapi_ReverseData(privateExponent); + + target = &keyBlobData->data[CAPI_PRIME_1_OFFSET(modSize)]; + nsslibc_memcpy(target, prime1->data, prime1->size); + prime1->data = target; + ckcapi_ReverseData(prime1); + + target = &keyBlobData->data[CAPI_PRIME_2_OFFSET(modSize)]; + nsslibc_memcpy(target, prime2->data, prime2->size); + prime2->data = target; + ckcapi_ReverseData(prime2); + + target = &keyBlobData->data[CAPI_EXPONENT_1_OFFSET(modSize)]; + nsslibc_memcpy(target, exponent1->data, exponent1->size); + exponent1->data = target; + ckcapi_ReverseData(exponent1); + + target = &keyBlobData->data[CAPI_EXPONENT_2_OFFSET(modSize)]; + nsslibc_memcpy(target, exponent2->data, exponent2->size); + exponent2->data = target; + ckcapi_ReverseData(exponent2); + + target = &keyBlobData->data[CAPI_COEFFICIENT_OFFSET(modSize)]; + nsslibc_memcpy(target, coefficient->data, coefficient->size); + coefficient->data = target; + ckcapi_ReverseData(coefficient); + + keyBlob->data = keyBlobData; + keyBlob->size = dataSize; + + return CKR_OK; + +loser: + nss_ZFreeIf(keyBlobData); + return error; +} + +static ckcapiInternalObject * +nss_ckcapi_CreatePrivateKey +( + NSSCKFWSession *fwSession, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + CK_RV *pError +) +{ + NSSItem modulus; + NSSItem publicExponent; + NSSItem privateExponent; + NSSItem exponent1; + NSSItem exponent2; + NSSItem prime1; + NSSItem prime2; + NSSItem coefficient; + NSSItem keyID; + NSSItem keyBlob; + ckcapiInternalObject *io = NULL; + char *providerName = NULL; + char *containerName = NULL; + char *idData = NULL; + CRYPT_KEY_PROV_INFO provInfo; + CRYPT_HASH_BLOB msKeyID; + CK_KEY_TYPE keyType; + HCRYPTPROV hProv = 0; + HCRYPTKEY hKey = 0; + PRBool decrypt; + DWORD keySpec; + DWORD msError; + BOOL rc; + + keyType = nss_ckcapi_GetULongAttribute + (CKA_KEY_TYPE, pTemplate, ulAttributeCount, pError); + if (CKR_OK != *pError) { + return (ckcapiInternalObject *)NULL; + } + if (CKK_RSA != keyType) { + *pError = CKR_ATTRIBUTE_VALUE_INVALID; + return (ckcapiInternalObject *)NULL; + } + + decrypt = nss_ckcapi_GetBoolAttribute(CKA_DECRYPT, + pTemplate, ulAttributeCount, pError); + if (CKR_TEMPLATE_INCOMPLETE == *pError) { + decrypt = PR_TRUE; /* default to true */ + } + decrypt = decrypt || nss_ckcapi_GetBoolAttribute(CKA_UNWRAP, + pTemplate, ulAttributeCount, pError); + if (CKR_TEMPLATE_INCOMPLETE == *pError) { + decrypt = PR_TRUE; /* default to true */ + } + keySpec = decrypt ? AT_KEYEXCHANGE : AT_SIGNATURE; + + *pError = nss_ckcapi_GetAttribute(CKA_MODULUS, pTemplate, + ulAttributeCount, &modulus); + if (CKR_OK != *pError) { + return (ckcapiInternalObject *)NULL; + } + *pError = nss_ckcapi_GetAttribute(CKA_PUBLIC_EXPONENT, pTemplate, + ulAttributeCount, &publicExponent); + if (CKR_OK != *pError) { + return (ckcapiInternalObject *)NULL; + } + *pError = nss_ckcapi_GetAttribute(CKA_PRIVATE_EXPONENT, pTemplate, + ulAttributeCount, &privateExponent); + if (CKR_OK != *pError) { + return (ckcapiInternalObject *)NULL; + } + *pError = nss_ckcapi_GetAttribute(CKA_PRIME_1, pTemplate, + ulAttributeCount, &prime1); + if (CKR_OK != *pError) { + return (ckcapiInternalObject *)NULL; + } + *pError = nss_ckcapi_GetAttribute(CKA_PRIME_2, pTemplate, + ulAttributeCount, &prime2); + if (CKR_OK != *pError) { + return (ckcapiInternalObject *)NULL; + } + *pError = nss_ckcapi_GetAttribute(CKA_EXPONENT_1, pTemplate, + ulAttributeCount, &exponent1); + if (CKR_OK != *pError) { + return (ckcapiInternalObject *)NULL; + } + *pError = nss_ckcapi_GetAttribute(CKA_EXPONENT_2, pTemplate, + ulAttributeCount, &exponent2); + if (CKR_OK != *pError) { + return (ckcapiInternalObject *)NULL; + } + *pError = nss_ckcapi_GetAttribute(CKA_COEFFICIENT, pTemplate, + ulAttributeCount, &coefficient); + if (CKR_OK != *pError) { + return (ckcapiInternalObject *)NULL; + } + *pError = nss_ckcapi_GetAttribute(CKA_ID, pTemplate, + ulAttributeCount, &keyID); + if (CKR_OK != *pError) { + return (ckcapiInternalObject *)NULL; + } + providerName = ckcapi_getDefaultProvider(pError); + if ((char *)NULL == providerName ) { + return (ckcapiInternalObject *)NULL; + } + containerName = ckcapi_getContainer(pError, &keyID); + if ((char *)NULL == providerName ) { + goto loser; + } + rc = CryptAcquireContext(&hProv, containerName, providerName, + PROV_RSA_FULL, CRYPT_NEWKEYSET); + if (!rc) { + msError = GetLastError(); + *pError = CKR_DEVICE_ERROR; + goto loser; + } + + *pError = ckcapi_buildPrivateKeyBlob( + &keyBlob, + &modulus, + &publicExponent, + &privateExponent, + &prime1, + &prime2, + &exponent1, + &exponent2, + &coefficient, + decrypt); + if (CKR_OK != *pError) { + goto loser; + } + + rc = CryptImportKey(hProv, keyBlob.data, keyBlob.size, + 0, CRYPT_EXPORTABLE, &hKey); + if (!rc) { + msError = GetLastError(); + *pError = CKR_DEVICE_ERROR; + goto loser; + } + + idData = nss_ZNEWARRAY(NULL, char, keyID.size); + if ((void *)NULL == idData) { + *pError = CKR_HOST_MEMORY; + goto loser; + } + nsslibc_memcpy(idData, keyID.data, keyID.size); + + provInfo.pwszContainerName = nss_ckcapi_UTF8ToWide(containerName); + provInfo.pwszProvName = nss_ckcapi_UTF8ToWide(providerName); + provInfo.dwProvType = PROV_RSA_FULL; + provInfo.dwFlags = 0; + provInfo.cProvParam = 0; + provInfo.rgProvParam = NULL; + provInfo.dwKeySpec = keySpec; + + msKeyID.cbData = keyID.size; + msKeyID.pbData = keyID.data; + + rc = CryptSetKeyIdentifierProperty(&msKeyID, CERT_KEY_PROV_INFO_PROP_ID, + 0, NULL, NULL, &provInfo); + if (!rc) { + goto loser; + } + + /* handle error here */ + io = nss_ZNEW(NULL, ckcapiInternalObject); + if ((ckcapiInternalObject *)NULL == io) { + *pError = CKR_HOST_MEMORY; + goto loser; + } + io->type = ckcapiBareKey; + io->objClass = CKO_PRIVATE_KEY; + io->u.key.provInfo = provInfo; + io->u.key.provName = providerName; + io->u.key.containerName = containerName; + io->u.key.hProv = hProv; /* save the handle */ + io->idData = idData; + io->id.data = idData; + io->id.size = keyID.size; + /* done with the key handle */ + CryptDestroyKey(hKey); + return io; + +loser: + nss_ZFreeIf(containerName); + nss_ZFreeIf(providerName); + nss_ZFreeIf(idData); + if (0 != hProv) { + CryptReleaseContext(hProv, 0); + } + if (0 != hKey) { + CryptDestroyKey(hKey); + } + return (ckcapiInternalObject *)NULL; +} + + +NSS_EXTERN NSSCKMDObject * +nss_ckcapi_CreateObject +( + NSSCKFWSession *fwSession, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + CK_RV *pError +) +{ + CK_OBJECT_CLASS objClass; + ckcapiInternalObject *io; + CK_BBOOL isToken; + + /* + * only create token objects + */ + isToken = nss_ckcapi_GetBoolAttribute(CKA_TOKEN, pTemplate, + ulAttributeCount, pError); + if (CKR_OK != *pError) { + return (NSSCKMDObject *) NULL; + } + if (!isToken) { + *pError = CKR_ATTRIBUTE_VALUE_INVALID; + return (NSSCKMDObject *) NULL; + } + + /* + * only create keys and certs. + */ + objClass = nss_ckcapi_GetULongAttribute(CKA_CLASS, pTemplate, + ulAttributeCount, pError); + if (CKR_OK != *pError) { + return (NSSCKMDObject *) NULL; + } +#ifdef notdef + if (objClass == CKO_PUBLIC_KEY) { + return CKR_OK; /* fake public key creation, happens as a side effect of + * private key creation */ + } +#endif + if (objClass == CKO_CERTIFICATE) { + io = nss_ckcapi_CreateCertificate(fwSession, pTemplate, + ulAttributeCount, pError); + } else if (objClass == CKO_PRIVATE_KEY) { + io = nss_ckcapi_CreatePrivateKey(fwSession, pTemplate, + ulAttributeCount, pError); + } else { + *pError = CKR_ATTRIBUTE_VALUE_INVALID; + } + + if ((ckcapiInternalObject *)NULL == io) { + return (NSSCKMDObject *) NULL; + } + return nss_ckcapi_CreateMDObject(NULL, io, pError); +} diff --git a/security/nss/lib/ckfw/capi/config.mk b/security/nss/lib/ckfw/capi/config.mk new file mode 100644 index 000000000..fdfc8cf09 --- /dev/null +++ b/security/nss/lib/ckfw/capi/config.mk @@ -0,0 +1,71 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is the Netscape security libraries. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1994-2000 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** +CONFIG_CVS_ID = "@(#) $RCSfile$ $Revision$ $Date$" + +# +# Override TARGETS variable so that only shared libraries +# are specifed as dependencies within rules.mk. +# + +TARGETS = $(SHARED_LIBRARY) +LIBRARY = +IMPORT_LIBRARY = +PROGRAM = + +ifeq (,$(filter-out WIN%,$(OS_TARGET))) + SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX) + RES = $(OBJDIR)/$(LIBRARY_NAME).res + RESNAME = $(LIBRARY_NAME).rc +endif + +ifdef BUILD_IDG + DEFINES += -DNSSDEBUG +endif + +# +# To create a loadable module on Darwin, we must use -bundle. +# +ifeq ($(OS_TARGET),Darwin) +DSO_LDOPTS = -bundle +endif + +ifeq ($(OS_TARGET),SunOS) +# The -R '$ORIGIN' linker option instructs this library to search for its +# dependencies in the same directory where it resides. +MKSHLIB += -R '$$ORIGIN' +endif + diff --git a/security/nss/lib/ckfw/capi/constants.c b/security/nss/lib/ckfw/capi/constants.c new file mode 100644 index 000000000..4e509da65 --- /dev/null +++ b/security/nss/lib/ckfw/capi/constants.c @@ -0,0 +1,98 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * Portions created by Red Hat, Inc, are Copyright (C) 2005 + * + * Contributor(s): + * Bob Relyea (rrelyea@redhat.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifdef DEBUG +static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$"; +#endif /* DEBUG */ + +/* + * ckcapi/constants.c + * + * Identification and other constants, all collected here in one place. + */ + +#ifndef NSSBASET_H +#include "nssbaset.h" +#endif /* NSSBASET_H */ + +#ifndef NSSCKT_H +#include "nssckt.h" +#endif /* NSSCKT_H */ + +#ifndef NSSCAPI_H +#include "nsscapi.h" +#endif /* NSSCAPI_H */ + +NSS_IMPLEMENT_DATA const CK_VERSION +nss_ckcapi_CryptokiVersion = { + NSS_CKCAPI_CRYPTOKI_VERSION_MAJOR, + NSS_CKCAPI_CRYPTOKI_VERSION_MINOR }; + +NSS_IMPLEMENT_DATA const NSSUTF8 * +nss_ckcapi_ManufacturerID = (NSSUTF8 *) "Mozilla Foundation"; + +NSS_IMPLEMENT_DATA const NSSUTF8 * +nss_ckcapi_LibraryDescription = (NSSUTF8 *) "NSS Access to Microsoft Certificate Store"; + +NSS_IMPLEMENT_DATA const CK_VERSION +nss_ckcapi_LibraryVersion = { + NSS_CKCAPI_LIBRARY_VERSION_MAJOR, + NSS_CKCAPI_LIBRARY_VERSION_MINOR}; + +NSS_IMPLEMENT_DATA const NSSUTF8 * +nss_ckcapi_SlotDescription = (NSSUTF8 *) "Microsoft Certificate Store"; + +NSS_IMPLEMENT_DATA const CK_VERSION +nss_ckcapi_HardwareVersion = { + NSS_CKCAPI_HARDWARE_VERSION_MAJOR, + NSS_CKCAPI_HARDWARE_VERSION_MINOR }; + +NSS_IMPLEMENT_DATA const CK_VERSION +nss_ckcapi_FirmwareVersion = { + NSS_CKCAPI_FIRMWARE_VERSION_MAJOR, + NSS_CKCAPI_FIRMWARE_VERSION_MINOR }; + +NSS_IMPLEMENT_DATA const NSSUTF8 * +nss_ckcapi_TokenLabel = (NSSUTF8 *) "Microsoft Certificate Store"; + +NSS_IMPLEMENT_DATA const NSSUTF8 * +nss_ckcapi_TokenModel = (NSSUTF8 *) "1"; + +NSS_IMPLEMENT_DATA const NSSUTF8 * +nss_ckcapi_TokenSerialNumber = (NSSUTF8 *) "1"; + diff --git a/security/nss/lib/ckfw/capi/crsa.c b/security/nss/lib/ckfw/capi/crsa.c new file mode 100644 index 000000000..ce0f42797 --- /dev/null +++ b/security/nss/lib/ckfw/capi/crsa.c @@ -0,0 +1,748 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Red Hat, Inc. + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Bob Relyea (rrelyea@redhat.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifdef DEBUG +static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$"; +#endif /* DEBUG */ + +#include "ckcapi.h" +#include "secdert.h" + +#define SSL3_SHAMD5_HASH_SIZE 36 /* LEN_MD5 (16) + LEN_SHA1 (20) */ + +/* + * ckcapi/crsa.c + * + * This file implements the NSSCKMDMechnaism and NSSCKMDCryptoOperation objects + * for the RSA operation on the CAPI cryptoki module. + */ + +/* + * write a Decimal value to a string + */ + +static char * +putDecimalString(char *cstr, unsigned long value) +{ + unsigned long tenpower; + int first = 1; + + for (tenpower=10000000; tenpower; tenpower /= 10) { + unsigned char digit = (unsigned char )(value/tenpower); + value = value % tenpower; + + /* drop leading zeros */ + if (first && (0 == digit)) { + continue; + } + first = 0; + *cstr++ = digit + '0'; + } + + /* if value was zero, put one of them out */ + if (first) { + *cstr++ = '0'; + } + return cstr; +} + + +/* + * Create a Capi OID string value from a DER OID + */ +static char * +nss_ckcapi_GetOidString +( + unsigned char *oidTag, + int oidTagSize, + CK_RV *pError +) +{ + unsigned char *oid; + char *oidStr; + char *cstr; + unsigned long value; + int oidSize; + + if (DER_OBJECT_ID != *oidTag) { + /* wasn't an oid */ + *pError = CKR_DATA_INVALID; + return NULL; + } + oid = nss_ckcapi_DERUnwrap(oidTag, oidTagSize, &oidSize, NULL); + + if (oidSize < 2) { + *pError = CKR_DATA_INVALID; + return NULL; + } + + oidStr = nss_ZNEWARRAY( NULL, char, oidSize*4 ); + if ((char *)NULL == oidStr) { + *pError = CKR_HOST_MEMORY; + return NULL; + } + cstr = oidStr; + cstr = putDecimalString(cstr, (*oid) / 40); + *cstr++ = '.'; + cstr = putDecimalString(cstr, (*oid) % 40); + oidSize--; + + value = 0; + while (oidSize--) { + oid++; + value = (value << 7) + (*oid & 0x7f); + if (0 == (*oid & 0x80)) { + *cstr++ = '.'; + cstr = putDecimalString(cstr, value); + value = 0; + } + } + + *cstr = 0; /* NULL terminate */ + + if (value != 0) { + nss_ZFreeIf(oidStr); + *pError = CKR_DATA_INVALID; + return NULL; + } + return oidStr; +} + + +/* + * PKCS #11 sign for RSA expects to take a fully DER-encoded hash value, + * which includes the hash OID. CAPI expects to take a Hash Context. While + * CAPI does have the capability of setting a raw hash value, it does not + * have the ability to sign an arbitrary value. This function tries to + * reduce the passed in data into something that CAPI could actually sign. + */ +static CK_RV +ckcapi_GetRawHash +( + const NSSItem *input, + NSSItem *hash, + ALG_ID *hashAlg +) +{ + unsigned char *current; + unsigned char *algid; + unsigned char *oid; + unsigned char *hashData; + char *oidStr; + CK_RV error; + int oidSize; + int size; + /* + * there are 2 types of hashes NSS typically tries to sign, regular + * RSA signature format (with encoded DER_OIDS), and SSL3 Signed hashes. + * CAPI knows not to add any oids to SSL3_Signed hashes, so if we have any + * random hash that is exactly the same size as an SSL3 hash, then we can + * just pass the data through. CAPI has know way of knowing if the value + * is really a combined hash or some other arbitrary data, so it's safe to + * handle this case first. + */ + if (SSL3_SHAMD5_HASH_SIZE == input->size) { + hash->data = input->data; + hash->size = input->size; + *hashAlg = CALG_SSL3_SHAMD5; + return CKR_OK; + } + + current = (unsigned char *)input->data; + + /* make sure we have a sequence tag */ + if ((DER_SEQUENCE|DER_CONSTRUCTED) != *current) { + return CKR_DATA_INVALID; + } + + /* parse the input block to get 1) the hash oid, and 2) the raw hash value. + * unfortunatly CAPI doesn't have a builtin function to do this work, so + * we go ahead and do it by hand here. + * + * format is: + * SEQUENCE { + * SECQUENCE { // algid + * OID {} // oid + * ANY {} // optional params + * } + * OCTECT {} // hash + */ + + /* unwrap */ + algid = nss_ckcapi_DERUnwrap(current,input->size, &size, NULL); + + if (algid+size != current+input->size) { + /* make sure there is not extra data at the end */ + return CKR_DATA_INVALID; + } + + if ((DER_SEQUENCE|DER_CONSTRUCTED) != *algid) { + /* wasn't an algid */ + return CKR_DATA_INVALID; + } + oid = nss_ckcapi_DERUnwrap(algid, size, &oidSize, &hashData); + + if (DER_OCTET_STRING != *hashData) { + /* wasn't a hash */ + return CKR_DATA_INVALID; + } + + /* get the real hash */ + current = hashData; + size = size - (hashData-algid); + hash->data = nss_ckcapi_DERUnwrap(current, size, &hash->size, NULL); + + /* get the real oid as a string. Again, Microsoft does not + * export anything that does this for us */ + oidStr = nss_ckcapi_GetOidString(oid, oidSize, &error); + if ((char *)NULL == oidStr ) { + return error; + } + + /* look up the hash alg from the oid (fortunately CAPI does to this) */ + *hashAlg = CertOIDToAlgId(oidStr); + nss_ZFreeIf(oidStr); + if (0 == *hashAlg) { + return CKR_HOST_MEMORY; + } + + /* hash looks reasonably consistent, we should be able to sign it now */ + return CKR_OK; +} + +/* + * So everyone else in the worlds stores their bignum data MSB first, but not + * Microsoft, we need to byte swap everything coming into and out of CAPI. + */ +void +ckcapi_ReverseData(NSSItem *item) +{ + int end = (item->size)-1; + int middle = (item->size)/2; + unsigned char *buf = item->data; + int i; + + for (i=0; i < middle; i++) { + unsigned char tmp = buf[i]; + buf[i] = buf[end-i]; + buf[end-i] = tmp; + } + return; +} + +typedef struct ckcapiInternalCryptoOperationRSAPrivStr + ckcapiInternalCryptoOperationRSAPriv; +struct ckcapiInternalCryptoOperationRSAPrivStr +{ + NSSCKMDCryptoOperation mdOperation; + NSSCKMDMechanism *mdMechanism; + ckcapiInternalObject *iKey; + HCRYPTPROV hProv; + DWORD keySpec; + HCRYPTKEY hKey; + NSSItem *buffer; +}; + +/* + * ckcapi_mdCryptoOperationRSAPriv_Create + */ +static NSSCKMDCryptoOperation * +ckcapi_mdCryptoOperationRSAPriv_Create +( + const NSSCKMDCryptoOperation *proto, + NSSCKMDMechanism *mdMechanism, + NSSCKMDObject *mdKey, + CK_RV *pError +) +{ + ckcapiInternalObject *iKey = (ckcapiInternalObject *)mdKey->etc; + const NSSItem *classItem = nss_ckcapi_FetchAttribute(iKey, CKA_CLASS); + const NSSItem *keyType = nss_ckcapi_FetchAttribute(iKey, CKA_KEY_TYPE); + ckcapiInternalCryptoOperationRSAPriv *iOperation; + CK_RV error; + HCRYPTPROV hProv; + DWORD keySpec; + HCRYPTKEY hKey; + + /* make sure we have the right objects */ + if (((const NSSItem *)NULL == classItem) || + (sizeof(CK_OBJECT_CLASS) != classItem->size) || + (CKO_PRIVATE_KEY != *(CK_OBJECT_CLASS *)classItem->data) || + ((const NSSItem *)NULL == keyType) || + (sizeof(CK_KEY_TYPE) != keyType->size) || + (CKK_RSA != *(CK_KEY_TYPE *)keyType->data)) { + *pError = CKR_KEY_TYPE_INCONSISTENT; + return (NSSCKMDCryptoOperation *)NULL; + } + + error = nss_ckcapi_FetchKeyContainer(iKey, &hProv, &keySpec, &hKey); + if (error != CKR_OK) { + *pError = error; + return (NSSCKMDCryptoOperation *)NULL; + } + + iOperation = nss_ZNEW(NULL, ckcapiInternalCryptoOperationRSAPriv); + if ((ckcapiInternalCryptoOperationRSAPriv *)NULL == iOperation) { + *pError = CKR_HOST_MEMORY; + return (NSSCKMDCryptoOperation *)NULL; + } + iOperation->mdMechanism = mdMechanism; + iOperation->iKey = iKey; + iOperation->hProv = hProv; + iOperation->keySpec = keySpec; + iOperation->hKey = hKey; + + nsslibc_memcpy(&iOperation->mdOperation, + proto, sizeof(NSSCKMDCryptoOperation)); + iOperation->mdOperation.etc = iOperation; + + return &iOperation->mdOperation; +} + +static CK_RV +ckcapi_mdCryptoOperationRSAPriv_Destroy +( + NSSCKMDCryptoOperation *mdOperation, + NSSCKFWCryptoOperation *fwOperation, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance +) +{ + ckcapiInternalCryptoOperationRSAPriv *iOperation = + (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc; + + if (iOperation->hKey) { + CryptDestroyKey(iOperation->hKey); + } + if (iOperation->buffer) { + nssItem_Destroy(iOperation->buffer); + } + nss_ZFreeIf(iOperation); + return CKR_OK; +} + +static CK_ULONG +ckcapi_mdCryptoOperationRSA_GetFinalLength +( + NSSCKMDCryptoOperation *mdOperation, + NSSCKFWCryptoOperation *fwOperation, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError +) +{ + ckcapiInternalCryptoOperationRSAPriv *iOperation = + (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc; + const NSSItem *modulus = + nss_ckcapi_FetchAttribute(iOperation->iKey, CKA_MODULUS); + + return modulus->size; +} + + +/* + * ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength + * we won't know the length until we actually decrypt the + * input block. Since we go to all the work to decrypt the + * the block, we'll save if for when the block is asked for + */ +static CK_ULONG +ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength +( + NSSCKMDCryptoOperation *mdOperation, + NSSCKFWCryptoOperation *fwOperation, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + const NSSItem *input, + CK_RV *pError +) +{ + ckcapiInternalCryptoOperationRSAPriv *iOperation = + (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc; + BOOL rc; + + /* Microsoft's Decrypt operation works in place. Since we don't want + * to trash our input buffer, we make a copy of it */ + iOperation->buffer = nssItem_Duplicate((NSSItem *)input, NULL, NULL); + if ((NSSItem *) NULL == iOperation->buffer) { + *pError = CKR_HOST_MEMORY; + return 0; + } + /* Sigh, reverse it */ + ckcapi_ReverseData(iOperation->buffer); + + rc = CryptDecrypt(iOperation->hKey, 0, TRUE, 0, + iOperation->buffer->data, &iOperation->buffer->size); + if (!rc) { + DWORD msError = GetLastError(); + switch (msError) { + case NTE_BAD_DATA: + *pError = CKR_ENCRYPTED_DATA_INVALID; + break; + case NTE_FAIL: + case NTE_BAD_UID: + *pError = CKR_DEVICE_ERROR; + break; + default: + *pError = CKR_GENERAL_ERROR; + } + return 0; + } + + return iOperation->buffer->size; +} + +/* + * ckcapi_mdCryptoOperationRSADecrypt_UpdateFinal + * + * NOTE: ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength is presumed to + * have been called previously. + */ +static CK_RV +ckcapi_mdCryptoOperationRSADecrypt_UpdateFinal +( + NSSCKMDCryptoOperation *mdOperation, + NSSCKFWCryptoOperation *fwOperation, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + const NSSItem *input, + NSSItem *output +) +{ + ckcapiInternalCryptoOperationRSAPriv *iOperation = + (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc; + NSSItem *buffer = iOperation->buffer; + + if ((NSSItem *)NULL == buffer) { + return CKR_GENERAL_ERROR; + } + nsslibc_memcpy(output->data, buffer->data, buffer->size); + output->size = buffer->size; + return CKR_OK; +} + +/* + * ckcapi_mdCryptoOperationRSASign_UpdateFinal + * + */ +static CK_RV +ckcapi_mdCryptoOperationRSASign_UpdateFinal +( + NSSCKMDCryptoOperation *mdOperation, + NSSCKFWCryptoOperation *fwOperation, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + const NSSItem *input, + NSSItem *output +) +{ + ckcapiInternalCryptoOperationRSAPriv *iOperation = + (ckcapiInternalCryptoOperationRSAPriv *)mdOperation->etc; + CK_RV error = CKR_OK; + DWORD msError; + NSSItem hash; + HCRYPTHASH hHash = 0; + ALG_ID hashAlg; + DWORD hashSize; + DWORD len; /* temp length value we throw away */ + BOOL rc; + + /* + * PKCS #11 sign for RSA expects to take a fully DER-encoded hash value, + * which includes the hash OID. CAPI expects to take a Hash Context. While + * CAPI does have the capability of setting a raw hash value, it does not + * have the ability to sign an arbitrary value. This function tries to + * reduce the passed in data into something that CAPI could actually sign. + */ + error = ckcapi_GetRawHash(input, &hash, &hashAlg); + if (CKR_OK != error) { + goto loser; + } + + rc = CryptCreateHash(iOperation->hProv, hashAlg, 0, 0, &hHash); + if (!rc) { + goto loser; + } + + /* make sure the hash lens match before we set it */ + len = sizeof(DWORD); + rc = CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE *)&hashSize, &len, 0); + if (!rc) { + goto loser; + } + + if (hash.size != hashSize) { + /* The input must have been bad for this to happen */ + error = CKR_DATA_INVALID; + goto loser; + } + + /* we have an explicit hash, set it, note that the length is + * implicit by the hashAlg used in create */ + rc = CryptSetHashParam(hHash, HP_HASHVAL, hash.data, 0); + if (!rc) { + goto loser; + } + + /* OK, we have the data in a hash structure, sign it! */ + rc = CryptSignHash(hHash, iOperation->keySpec, NULL, 0, + output->data, &output->size); + if (!rc) { + goto loser; + } + + /* Don't return a signature that might have been broken because of a cosmic + * ray, or a broken processor, verify that it is valid... */ + rc = CryptVerifySignature(hHash, output->data, output->size, + iOperation->hKey, NULL, 0); + if (!rc) { + goto loser; + } + + /* OK, Microsoft likes to do things completely differently than anyone + * else. We need to reverse the data we recieved here */ + ckcapi_ReverseData(output); + CryptDestroyHash(hHash); + return CKR_OK; + +loser: + /* map the microsoft error */ + if (CKR_OK == error) { + msError = GetLastError(); + switch (msError) { + case ERROR_NOT_ENOUGH_MEMORY: + error = CKR_HOST_MEMORY; + break; + case NTE_NO_MEMORY: + error = CKR_DEVICE_MEMORY; + break; + case ERROR_MORE_DATA: + return CKR_BUFFER_TOO_SMALL; + case ERROR_INVALID_PARAMETER: /* these params were derived from the */ + case ERROR_INVALID_HANDLE: /* inputs, so if they are bad, the input */ + case NTE_BAD_ALGID: /* data is bad */ + case NTE_BAD_HASH: + error = CKR_DATA_INVALID; + break; + case ERROR_BUSY: + case NTE_FAIL: + case NTE_BAD_UID: + error = CKR_DEVICE_ERROR; + break; + default: + error = CKR_GENERAL_ERROR; + break; + } + } + if (hHash) { + CryptDestroyHash(hHash); + } + return error; +} + + +NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation +ckcapi_mdCryptoOperationRSADecrypt_proto = { + NULL, /* etc */ + ckcapi_mdCryptoOperationRSAPriv_Destroy, + NULL, /* GetFinalLengh - not needed for one shot Decrypt/Encrypt */ + ckcapi_mdCryptoOperationRSADecrypt_GetOperationLength, + NULL, /* Final - not needed for one shot operation */ + NULL, /* Update - not needed for one shot operation */ + NULL, /* DigetUpdate - not needed for one shot operation */ + ckcapi_mdCryptoOperationRSADecrypt_UpdateFinal, + NULL, /* UpdateCombo - not needed for one shot operation */ + NULL, /* DigetKey - not needed for one shot operation */ + (void *)NULL /* null terminator */ +}; + +NSS_IMPLEMENT_DATA const NSSCKMDCryptoOperation +ckcapi_mdCryptoOperationRSASign_proto = { + NULL, /* etc */ + ckcapi_mdCryptoOperationRSAPriv_Destroy, + ckcapi_mdCryptoOperationRSA_GetFinalLength, + NULL, /* GetOperationLengh - not needed for one shot Sign/Verify */ + NULL, /* Final - not needed for one shot operation */ + NULL, /* Update - not needed for one shot operation */ + NULL, /* DigetUpdate - not needed for one shot operation */ + ckcapi_mdCryptoOperationRSASign_UpdateFinal, + NULL, /* UpdateCombo - not needed for one shot operation */ + NULL, /* DigetKey - not needed for one shot operation */ + (void *)NULL /* null terminator */ +}; + +/********** NSSCKMDMechansim functions ***********************/ +/* + * ckcapi_mdMechanismRSA_Destroy + */ +static void +ckcapi_mdMechanismRSA_Destroy +( + NSSCKMDMechanism *mdMechanism, + NSSCKFWMechanism *fwMechanism, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance +) +{ + nss_ZFreeIf(fwMechanism); +} + +/* + * ckcapi_mdMechanismRSA_GetMinKeySize + */ +static CK_ULONG +ckcapi_mdMechanismRSA_GetMinKeySize +( + NSSCKMDMechanism *mdMechanism, + NSSCKFWMechanism *fwMechanism, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError +) +{ + return 384; +} + +/* + * ckcapi_mdMechanismRSA_GetMaxKeySize + */ +static CK_ULONG +ckcapi_mdMechanismRSA_GetMaxKeySize +( + NSSCKMDMechanism *mdMechanism, + NSSCKFWMechanism *fwMechanism, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError +) +{ + return 16384; +} + +/* + * ckcapi_mdMechanismRSA_DecryptInit + */ +static NSSCKMDCryptoOperation * +ckcapi_mdMechanismRSA_DecryptInit +( + NSSCKMDMechanism *mdMechanism, + NSSCKFWMechanism *fwMechanism, + CK_MECHANISM *pMechanism, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + NSSCKMDObject *mdKey, + NSSCKFWObject *fwKey, + CK_RV *pError +) +{ + return ckcapi_mdCryptoOperationRSAPriv_Create( + &ckcapi_mdCryptoOperationRSADecrypt_proto, + mdMechanism, mdKey, pError); +} + +/* + * ckcapi_mdMechanismRSA_SignInit + */ +static NSSCKMDCryptoOperation * +ckcapi_mdMechanismRSA_SignInit +( + NSSCKMDMechanism *mdMechanism, + NSSCKFWMechanism *fwMechanism, + CK_MECHANISM *pMechanism, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + NSSCKMDObject *mdKey, + NSSCKFWObject *fwKey, + CK_RV *pError +) +{ + return ckcapi_mdCryptoOperationRSAPriv_Create( + &ckcapi_mdCryptoOperationRSASign_proto, + mdMechanism, mdKey, pError); +} + + +NSS_IMPLEMENT_DATA const NSSCKMDMechanism +nss_ckcapi_mdMechanismRSA = { + (void *)NULL, /* etc */ + ckcapi_mdMechanismRSA_Destroy, + ckcapi_mdMechanismRSA_GetMinKeySize, + ckcapi_mdMechanismRSA_GetMaxKeySize, + NULL, /* GetInHardware - default false */ + NULL, /* EncryptInit - default errs */ + ckcapi_mdMechanismRSA_DecryptInit, + NULL, /* DigestInit - default errs*/ + ckcapi_mdMechanismRSA_SignInit, + NULL, /* VerifyInit - default errs */ + ckcapi_mdMechanismRSA_SignInit, /* SignRecoverInit */ + NULL, /* VerifyRecoverInit - default errs */ + NULL, /* GenerateKey - default errs */ + NULL, /* GenerateKeyPair - default errs */ + NULL, /* GetWrapKeyLength - default errs */ + NULL, /* WrapKey - default errs */ + NULL, /* UnwrapKey - default errs */ + NULL, /* DeriveKey - default errs */ + (void *)NULL /* null terminator */ +}; diff --git a/security/nss/lib/ckfw/capi/csession.c b/security/nss/lib/ckfw/capi/csession.c new file mode 100644 index 000000000..f0abd6d0b --- /dev/null +++ b/security/nss/lib/ckfw/capi/csession.c @@ -0,0 +1,131 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * Portions created by Red Hat, Inc, are Copyright (C) 2005 + * + * Contributor(s): + * Bob Relyea (rrelyea@redhat.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifdef DEBUG +static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$"; +#endif /* DEBUG */ + +#include "ckcapi.h" + +/* + * ckcapi/csession.c + * + * This file implements the NSSCKMDSession object for the + * "nss to capi" cryptoki module. + */ + +static NSSCKMDFindObjects * +ckcapi_mdSession_FindObjectsInit +( + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + CK_RV *pError +) +{ + return nss_ckcapi_FindObjectsInit(fwSession, pTemplate, ulAttributeCount, pError); +} + +static NSSCKMDObject * +ckcapi_mdSession_CreateObject +( + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + NSSArena *arena, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + CK_RV *pError +) +{ + return nss_ckcapi_CreateObject(fwSession, pTemplate, ulAttributeCount, pError); +} + +NSS_IMPLEMENT NSSCKMDSession * +nss_ckcapi_CreateSession +( + NSSCKFWSession *fwSession, + CK_RV *pError +) +{ + NSSArena *arena; + NSSCKMDSession *rv; + + arena = NSSCKFWSession_GetArena(fwSession, pError); + if( (NSSArena *)NULL == arena ) { + return (NSSCKMDSession *)NULL; + } + + rv = nss_ZNEW(arena, NSSCKMDSession); + if( (NSSCKMDSession *)NULL == rv ) { + *pError = CKR_HOST_MEMORY; + return (NSSCKMDSession *)NULL; + } + + /* + * rv was zeroed when allocated, so we only + * need to set the non-zero members. + */ + + rv->etc = (void *)fwSession; + /* rv->Close */ + /* rv->GetDeviceError */ + /* rv->Login */ + /* rv->Logout */ + /* rv->InitPIN */ + /* rv->SetPIN */ + /* rv->GetOperationStateLen */ + /* rv->GetOperationState */ + /* rv->SetOperationState */ + rv->CreateObject = ckcapi_mdSession_CreateObject; + /* rv->CopyObject */ + rv->FindObjectsInit = ckcapi_mdSession_FindObjectsInit; + /* rv->SeedRandom */ + /* rv->GetRandom */ + /* rv->null */ + + return rv; +} diff --git a/security/nss/lib/ckfw/capi/cslot.c b/security/nss/lib/ckfw/capi/cslot.c new file mode 100644 index 000000000..1c42c107d --- /dev/null +++ b/security/nss/lib/ckfw/capi/cslot.c @@ -0,0 +1,129 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * Portions created by Red Hat, Inc, are Copyright (C) 2005 + * + * Contributor(s): + * Bob Relyea (rrelyea@redhat.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifdef DEBUG +static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$"; +#endif /* DEBUG */ + +#include "ckcapi.h" + +/* + * ckcapi/cslot.c + * + * This file implements the NSSCKMDSlot object for the + * "nss to capi" cryptoki module. + */ + +static NSSUTF8 * +ckcapi_mdSlot_GetSlotDescription +( + NSSCKMDSlot *mdSlot, + NSSCKFWSlot *fwSlot, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError +) +{ + return (NSSUTF8 *)nss_ckcapi_SlotDescription; +} + +static NSSUTF8 * +ckcapi_mdSlot_GetManufacturerID +( + NSSCKMDSlot *mdSlot, + NSSCKFWSlot *fwSlot, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError +) +{ + return (NSSUTF8 *)nss_ckcapi_ManufacturerID; +} + +static CK_VERSION +ckcapi_mdSlot_GetHardwareVersion +( + NSSCKMDSlot *mdSlot, + NSSCKFWSlot *fwSlot, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance +) +{ + return nss_ckcapi_HardwareVersion; +} + +static CK_VERSION +ckcapi_mdSlot_GetFirmwareVersion +( + NSSCKMDSlot *mdSlot, + NSSCKFWSlot *fwSlot, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance +) +{ + return nss_ckcapi_FirmwareVersion; +} + +static NSSCKMDToken * +ckcapi_mdSlot_GetToken +( + NSSCKMDSlot *mdSlot, + NSSCKFWSlot *fwSlot, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError +) +{ + return (NSSCKMDToken *)&nss_ckcapi_mdToken; +} + +NSS_IMPLEMENT_DATA const NSSCKMDSlot +nss_ckcapi_mdSlot = { + (void *)NULL, /* etc */ + NULL, /* Initialize */ + NULL, /* Destroy */ + ckcapi_mdSlot_GetSlotDescription, + ckcapi_mdSlot_GetManufacturerID, + NULL, /* GetTokenPresent -- defaults to true */ + NULL, /* GetRemovableDevice -- defaults to false */ + NULL, /* GetHardwareSlot -- defaults to false */ + ckcapi_mdSlot_GetHardwareVersion, + ckcapi_mdSlot_GetFirmwareVersion, + ckcapi_mdSlot_GetToken, + (void *)NULL /* null terminator */ +}; diff --git a/security/nss/lib/ckfw/capi/ctoken.c b/security/nss/lib/ckfw/capi/ctoken.c new file mode 100644 index 000000000..bce2c17e2 --- /dev/null +++ b/security/nss/lib/ckfw/capi/ctoken.c @@ -0,0 +1,246 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * Portions created by Red Hat, Inc, are Copyright (C) 2005 + * + * Contributor(s): + * Bob Relyea (rrelyea@redhat.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifdef DEBUG +static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$"; +#endif /* DEBUG */ + +#include "ckcapi.h" + +/* + * ckcapi/ctoken.c + * + * This file implements the NSSCKMDToken object for the + * "nss to capi" cryptoki module. + */ + +static NSSUTF8 * +ckcapi_mdToken_GetLabel +( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError +) +{ + return (NSSUTF8 *)nss_ckcapi_TokenLabel; +} + +static NSSUTF8 * +ckcapi_mdToken_GetManufacturerID +( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError +) +{ + return (NSSUTF8 *)nss_ckcapi_ManufacturerID; +} + +static NSSUTF8 * +ckcapi_mdToken_GetModel +( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError +) +{ + return (NSSUTF8 *)nss_ckcapi_TokenModel; +} + +static NSSUTF8 * +ckcapi_mdToken_GetSerialNumber +( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError +) +{ + return (NSSUTF8 *)nss_ckcapi_TokenSerialNumber; +} + +static CK_BBOOL +ckcapi_mdToken_GetIsWriteProtected +( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance +) +{ + return CK_FALSE; +} + +/* fake out Mozilla so we don't try to initialize the token */ +static CK_BBOOL +ckcapi_mdToken_GetUserPinInitialized +( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance +) +{ + return CK_TRUE; +} + +static CK_VERSION +ckcapi_mdToken_GetHardwareVersion +( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance +) +{ + return nss_ckcapi_HardwareVersion; +} + +static CK_VERSION +ckcapi_mdToken_GetFirmwareVersion +( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance +) +{ + return nss_ckcapi_FirmwareVersion; +} + +static NSSCKMDSession * +ckcapi_mdToken_OpenSession +( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + NSSCKFWSession *fwSession, + CK_BBOOL rw, + CK_RV *pError +) +{ + return nss_ckcapi_CreateSession(fwSession, pError); +} + +static CK_ULONG +ckcapi_mdToken_GetMechanismCount +( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance +) +{ + return (CK_ULONG)1; +} + +static CK_RV +ckcapi_mdToken_GetMechanismTypes +( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_MECHANISM_TYPE types[] +) +{ + types[0] = CKM_RSA_PKCS; + return CKR_OK; +} + +static NSSCKMDMechanism * +ckcapi_mdToken_GetMechanism +( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_MECHANISM_TYPE which, + CK_RV *pError +) +{ + if (which != CKM_RSA_PKCS) { + *pError = CKR_MECHANISM_INVALID; + return (NSSCKMDMechanism *)NULL; + } + return (NSSCKMDMechanism *)&nss_ckcapi_mdMechanismRSA; +} + +NSS_IMPLEMENT_DATA const NSSCKMDToken +nss_ckcapi_mdToken = { + (void *)NULL, /* etc */ + NULL, /* Setup */ + NULL, /* Invalidate */ + NULL, /* InitToken -- default errs */ + ckcapi_mdToken_GetLabel, + ckcapi_mdToken_GetManufacturerID, + ckcapi_mdToken_GetModel, + ckcapi_mdToken_GetSerialNumber, + NULL, /* GetHasRNG -- default is false */ + ckcapi_mdToken_GetIsWriteProtected, + NULL, /* GetLoginRequired -- default is false */ + ckcapi_mdToken_GetUserPinInitialized, + NULL, /* GetRestoreKeyNotNeeded -- irrelevant */ + NULL, /* GetHasClockOnToken -- default is false */ + NULL, /* GetHasProtectedAuthenticationPath -- default is false */ + NULL, /* GetSupportsDualCryptoOperations -- default is false */ + NULL, /* GetMaxSessionCount -- default is CK_UNAVAILABLE_INFORMATION */ + NULL, /* GetMaxRwSessionCount -- default is CK_UNAVAILABLE_INFORMATION */ + NULL, /* GetMaxPinLen -- irrelevant */ + NULL, /* GetMinPinLen -- irrelevant */ + NULL, /* GetTotalPublicMemory -- default is CK_UNAVAILABLE_INFORMATION */ + NULL, /* GetFreePublicMemory -- default is CK_UNAVAILABLE_INFORMATION */ + NULL, /* GetTotalPrivateMemory -- default is CK_UNAVAILABLE_INFORMATION */ + NULL, /* GetFreePrivateMemory -- default is CK_UNAVAILABLE_INFORMATION */ + ckcapi_mdToken_GetHardwareVersion, + ckcapi_mdToken_GetFirmwareVersion, + NULL, /* GetUTCTime -- no clock */ + ckcapi_mdToken_OpenSession, + ckcapi_mdToken_GetMechanismCount, + ckcapi_mdToken_GetMechanismTypes, + ckcapi_mdToken_GetMechanism, + (void *)NULL /* null terminator */ +}; diff --git a/security/nss/lib/ckfw/capi/manifest.mn b/security/nss/lib/ckfw/capi/manifest.mn new file mode 100644 index 000000000..8959e5d2d --- /dev/null +++ b/security/nss/lib/ckfw/capi/manifest.mn @@ -0,0 +1,66 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is the Netscape security libraries. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1994-2000 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** +MANIFEST_CVS_ID = "@(#) $RCSfile$ $Revision$ $Date$" + +CORE_DEPTH = ../../../.. + +MODULE = nss +MAPFILE = $(OBJDIR)/nsscapi.def + +EXPORTS = \ + nsscapi.h \ + $(NULL) + +CSRCS = \ + anchor.c \ + constants.c \ + cfind.c \ + cinst.c \ + cobject.c \ + crsa.c \ + csession.c \ + cslot.c \ + ctoken.c \ + ckcapiver.c \ + staticobj.c \ + $(NULL) + +REQUIRES = nspr + +LIBRARY_NAME = nsscapi + +#EXTRA_SHARED_LIBS = -L$(DIST)/lib -lnssckfw -lnssb -lplc4 -lplds4 diff --git a/security/nss/lib/ckfw/capi/nsscapi.def b/security/nss/lib/ckfw/capi/nsscapi.def new file mode 100644 index 000000000..0e6106c62 --- /dev/null +++ b/security/nss/lib/ckfw/capi/nsscapi.def @@ -0,0 +1,58 @@ +;+# +;+# ***** BEGIN LICENSE BLOCK ***** +;+# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +;+# +;+# The contents of this file are subject to the Mozilla Public License Version +;+# 1.1 (the "License"); you may not use this file except in compliance with +;+# the License. You may obtain a copy of the License at +;+# http://www.mozilla.org/MPL/ +;+# +;+# Software distributed under the License is distributed on an "AS IS" basis, +;+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +;+# for the specific language governing rights and limitations under the +;+# License. +;+# +;+# The Original Code is the Netscape security libraries. +;+# +;+# The Initial Developer of the Original Code is +;+# Netscape Communications Corporation. +;+# Portions created by the Initial Developer are Copyright (C) 2003 +;+# the Initial Developer. All Rights Reserved. +;+# +;+# Contributor(s): +;+# +;+# Alternatively, the contents of this file may be used under the terms of +;+# either the GNU General Public License Version 2 or later (the "GPL"), or +;+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +;+# in which case the provisions of the GPL or the LGPL are applicable instead +;+# of those above. If you wish to allow use of your version of this file only +;+# under the terms of either the GPL or the LGPL, and not to allow others to +;+# use your version of this file under the terms of the MPL, indicate your +;+# decision by deleting the provisions above and replace them with the notice +;+# and other provisions required by the GPL or the LGPL. If you do not delete +;+# the provisions above, a recipient may use your version of this file under +;+# the terms of any one of the MPL, the GPL or the LGPL. +;+# +;+# ***** END LICENSE BLOCK ***** +;+# +;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS +;+# 1. For all unix platforms, the string ";-" means "remove this line" +;+# 2. For all unix platforms, the string " DATA " will be removed from any +;+# line on which it occurs. +;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX. +;+# On AIX, lines containing ";+" will be removed. +;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed. +;+# 5. For all unix platforms, after the above processing has taken place, +;+# all characters after the first ";" on the line will be removed. +;+# And for AIX, the first ";" will also be removed. +;+# This file is passed directly to windows. Since ';' is a comment, all UNIX +;+# directives are hidden behind ";", ";+", and ";-" +;+ +;+NSS_3.1 { # NSS 3.1 release +;+ global: +LIBRARY nsscapi ;- +EXPORTS ;- +C_GetFunctionList; +;+ local: +;+*; +;+}; diff --git a/security/nss/lib/ckfw/capi/nsscapi.h b/security/nss/lib/ckfw/capi/nsscapi.h new file mode 100644 index 000000000..1d80487e9 --- /dev/null +++ b/security/nss/lib/ckfw/capi/nsscapi.h @@ -0,0 +1,75 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * Portions created by Red Hat, Inc, are Copyright (C) 2005 + * + * Contributor(s): + * Bob Relyea (rrelyea@redhat.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef NSSCAPI_H +#define NSSCAPI_H + +/* + * NSS CKCAPI Version numbers. + * + * These are the version numbers for the capi module packaged with + * this release on NSS. To determine the version numbers of the builtin + * module you are using, use the appropriate PKCS #11 calls. + * + * These version numbers detail changes to the PKCS #11 interface. They map + * to the PKCS #11 spec versions. + */ +#define NSS_CKCAPI_CRYPTOKI_VERSION_MAJOR 2 +#define NSS_CKCAPI_CRYPTOKI_VERSION_MINOR 20 + +/* These version numbers detail the changes + * to the list of trusted certificates. + * + * NSS_CKCAPI_LIBRARY_VERSION_MINOR is a CK_BYTE. It's not clear + * whether we may use its full range (0-255) or only 0-99 because + * of the comment in the CK_VERSION type definition. + */ +#define NSS_CKCAPI_LIBRARY_VERSION_MAJOR 1 +#define NSS_CKCAPI_LIBRARY_VERSION_MINOR 1 +#define NSS_CKCAPI_LIBRARY_VERSION "1.1" + +/* These version numbers detail the semantic changes to the ckfw engine. */ +#define NSS_CKCAPI_HARDWARE_VERSION_MAJOR 1 +#define NSS_CKCAPI_HARDWARE_VERSION_MINOR 0 + +/* These version numbers detail the semantic changes to ckbi itself + * (new PKCS #11 objects), etc. */ +#define NSS_CKCAPI_FIRMWARE_VERSION_MAJOR 1 +#define NSS_CKCAPI_FIRMWARE_VERSION_MINOR 0 + +#endif /* NSSCKBI_H */ diff --git a/security/nss/lib/ckfw/capi/nsscapi.rc b/security/nss/lib/ckfw/capi/nsscapi.rc new file mode 100644 index 000000000..d5024f7a6 --- /dev/null +++ b/security/nss/lib/ckfw/capi/nsscapi.rc @@ -0,0 +1,97 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsscapi.h" +#include <winver.h> + +#define MY_LIBNAME "nsscapi" +#define MY_FILEDESCRIPTION "NSS Access to Microsoft CAPI" + +#ifdef _DEBUG +#define MY_DEBUG_STR " (debug)" +#define MY_FILEFLAGS_1 VS_FF_DEBUG +#else +#define MY_DEBUG_STR "" +#define MY_FILEFLAGS_1 0x0L +#endif +#if NSS_BETA +#define MY_FILEFLAGS_2 MY_FILEFLAGS_1|VS_FF_PRERELEASE +#else +#define MY_FILEFLAGS_2 MY_FILEFLAGS_1 +#endif + +#ifdef WINNT +#define MY_FILEOS VOS_NT_WINDOWS32 +#else +#define MY_FILEOS VOS__WINDOWS32 +#endif + +#define MY_INTERNAL_NAME MY_LIBNAME + +///////////////////////////////////////////////////////////////////////////// +// +// Version-information resource +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION NSS_CKCAPI_LIBRARY_VERSION_MAJOR,NSS_CKCAPI_LIBRARY_VERSION_MINOR,0,0 + PRODUCTVERSION NSS_CKCAPI_LIBRARY_VERSION_MAJOR,NSS_CKCAPI_LIBRARY_VERSION_MINOR,0,0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS MY_FILEFLAGS_2 + FILEOS MY_FILEOS + FILETYPE VFT_DLL + FILESUBTYPE 0x0L // not used + +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" // Lang=US English, CharSet=Unicode + BEGIN + VALUE "CompanyName", "Mozilla Foundation\0" + VALUE "FileDescription", MY_FILEDESCRIPTION MY_DEBUG_STR "\0" + VALUE "FileVersion", NSS_CKCAPI_LIBRARY_VERSION "\0" + VALUE "InternalName", MY_INTERNAL_NAME "\0" + VALUE "LegalCopyright", "Copyright \251 1994-2005 Netscape Communications Corporation\0" + VALUE "OriginalFilename", MY_INTERNAL_NAME ".dll\0" + VALUE "ProductName", "Network Security Services\0" + VALUE "ProductVersion", NSS_CKCAPI_LIBRARY_VERSION "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/security/nss/lib/ckfw/capi/staticobj.c b/security/nss/lib/ckfw/capi/staticobj.c new file mode 100644 index 000000000..8cfd8fbdd --- /dev/null +++ b/security/nss/lib/ckfw/capi/staticobj.c @@ -0,0 +1,74 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * Portions created by Red Hat, Inc, are Copyright (C) 2005 + * + * Contributor(s): + * Bob Relyea (rrelyea@redhat.com) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifdef DEBUG +static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$""; @(#) $RCSfile$ $Revision$ $Date$"; +#endif /* DEBUG */ + +#ifndef CKCAPI_H +#include "ckcapi.h" +#endif /* CKCAPI_H */ + +static const CK_TRUST ckt_netscape_valid = CKT_NETSCAPE_VALID; +static const CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE; +static const CK_TRUST ckt_netscape_trusted_delegator = CKT_NETSCAPE_TRUSTED_DELEGATOR; +static const CK_OBJECT_CLASS cko_netscape_trust = CKO_NETSCAPE_TRUST; +static const CK_BBOOL ck_true = CK_TRUE; +static const CK_OBJECT_CLASS cko_data = CKO_DATA; +static const CK_CERTIFICATE_TYPE ckc_x_509 = CKC_X_509; +static const CK_BBOOL ck_false = CK_FALSE; +static const CK_OBJECT_CLASS cko_netscape_builtin_root_list = CKO_NETSCAPE_BUILTIN_ROOT_LIST; + +/* example of a static object */ +static const CK_ATTRIBUTE_TYPE nss_ckcapi_types_1 [] = { + CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_MODIFIABLE, CKA_LABEL +}; + +static const NSSItem nss_ckcapi_items_1 [] = { + { (void *)&cko_data, (PRUint32)sizeof(CK_OBJECT_CLASS) }, + { (void *)&ck_true, (PRUint32)sizeof(CK_BBOOL) }, + { (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL) }, + { (void *)&ck_false, (PRUint32)sizeof(CK_BBOOL) }, + { (void *)"Mozilla CAPI Access", (PRUint32)20 } +}; + +PR_IMPLEMENT_DATA(ckcapiInternalObject) nss_ckcapi_data[] = { + { ckcapiRaw, { 5, nss_ckcapi_types_1, nss_ckcapi_items_1} , {NULL} }, +}; + +PR_IMPLEMENT_DATA(const PRUint32) nss_ckcapi_nObjects = 1; diff --git a/security/nss/lib/ckfw/ckfwm.h b/security/nss/lib/ckfw/ckfwm.h index d54cff194..542bc390c 100644 --- a/security/nss/lib/ckfw/ckfwm.h +++ b/security/nss/lib/ckfw/ckfwm.h @@ -161,11 +161,4 @@ nssCKFWHash_Iterate void *closure ); -NSS_EXTERN CK_RV -nssSetLockArgs( - CK_C_INITIALIZE_ARGS_PTR pInitArgs, - CryptokiLockingState* returned -); - - #endif /* CKFWM_H */ diff --git a/security/nss/lib/ckfw/manifest.mn b/security/nss/lib/ckfw/manifest.mn index 345ea81e1..f5e9fb953 100644 --- a/security/nss/lib/ckfw/manifest.mn +++ b/security/nss/lib/ckfw/manifest.mn @@ -68,7 +68,6 @@ CSRCS = \ hash.c \ instance.c \ mutex.c \ - nsprstub.c \ object.c \ session.c \ sessobj.c \ diff --git a/security/nss/lib/ckfw/mutex.c b/security/nss/lib/ckfw/mutex.c index b9fa7c6be..0b6b80019 100644 --- a/security/nss/lib/ckfw/mutex.c +++ b/security/nss/lib/ckfw/mutex.c @@ -67,11 +67,7 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$"; */ struct NSSCKFWMutexStr { - CK_VOID_PTR etc; - - CK_DESTROYMUTEX Destroy; - CK_LOCKMUTEX Lock; - CK_UNLOCKMUTEX Unlock; + PRLock *lock; }; #ifdef DEBUG @@ -144,23 +140,13 @@ nssCKFWMutex_Create *pError = CKR_HOST_MEMORY; return (NSSCKFWMutex *)NULL; } - - switch (LockingState) - { - default: - case SingleThreaded: - *pError = CKR_OK; - mutex->Destroy = (CK_DESTROYMUTEX)mutex_noop; - mutex->Lock = (CK_LOCKMUTEX )mutex_noop; - mutex->Unlock = (CK_UNLOCKMUTEX )mutex_noop; - break; - - case MultiThreaded: - *pError = pInitArgs->CreateMutex(&mutex->etc); - mutex->Destroy = pInitArgs->DestroyMutex; - mutex->Lock = pInitArgs->LockMutex; - mutex->Unlock = pInitArgs->UnlockMutex; - break; + *pError = CKR_OK; + mutex->lock = NULL; + if (LockingState == MultiThreaded) { + mutex->lock = PR_NewLock(); + if (!mutex->lock) { + *pError = CKR_HOST_MEMORY; /* we couldn't get the resource */ + } } if( CKR_OK != *pError ) { @@ -171,6 +157,9 @@ nssCKFWMutex_Create #ifdef DEBUG *pError = mutex_add_pointer(mutex); if( CKR_OK != *pError ) { + if (mutex->lock) { + PR_DestroyLock(mutex->lock); + } (void)nss_ZFreeIf(mutex); return (NSSCKFWMutex *)NULL; } @@ -197,8 +186,10 @@ nssCKFWMutex_Destroy return rv; } #endif /* NSSDEBUG */ - - rv = mutex->Destroy(mutex->etc); + + if (mutex->lock) { + PR_DestroyLock(mutex->lock); + } #ifdef DEBUG (void)mutex_remove_pointer(mutex); @@ -224,8 +215,11 @@ nssCKFWMutex_Lock return rv; } #endif /* NSSDEBUG */ + if (mutex->lock) { + PR_Lock(mutex->lock); + } - return mutex->Lock(mutex->etc); + return CKR_OK; } /* @@ -238,14 +232,24 @@ nssCKFWMutex_Unlock NSSCKFWMutex *mutex ) { + PRStatus nrv; #ifdef NSSDEBUG CK_RV rv = nssCKFWMutex_verifyPointer(mutex); + if( CKR_OK != rv ) { return rv; } #endif /* NSSDEBUG */ - return mutex->Unlock(mutex->etc); + if (!mutex->lock) + return CKR_OK; + + nrv = PR_Unlock(mutex->lock); + + /* if unlock fails, either we have a programming error, or we have + * some sort of hardware failure... in either case return CKR_DEVICE_ERROR. + */ + return nrv == PR_SUCCESS ? CKR_OK : CKR_DEVICE_ERROR; } /* diff --git a/security/nss/lib/ckfw/wrap.c b/security/nss/lib/ckfw/wrap.c index eaa504bb3..b9af321a3 100644 --- a/security/nss/lib/ckfw/wrap.c +++ b/security/nss/lib/ckfw/wrap.c @@ -125,6 +125,46 @@ static const char CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$"; * NSSCKFWC_CancelFunction */ +/* figure out out locking semantics */ +static CK_RV +nssCKFW_GetThreadSafeState(CK_C_INITIALIZE_ARGS_PTR pInitArgs, + CryptokiLockingState *pLocking_state) { + int functionCount = 0; + + /* parsed according to (PKCS #11 Section 11.4) */ + /* no args, the degenerate version of case 1 */ + if (!pInitArgs) { + *pLocking_state = SingleThreaded; + return CKR_OK; + } + + /* CKF_OS_LOCKING_OK set, Cases 2 and 4 */ + if (pInitArgs->flags & CKF_OS_LOCKING_OK) { + *pLocking_state = MultiThreaded; + return CKR_OK; + } + if ((CK_CREATEMUTEX) NULL != pInitArgs->CreateMutex) functionCount++; + if ((CK_DESTROYMUTEX) NULL != pInitArgs->DestroyMutex) functionCount++; + if ((CK_LOCKMUTEX) NULL != pInitArgs->LockMutex) functionCount++; + if ((CK_UNLOCKMUTEX) NULL != pInitArgs->UnlockMutex) functionCount++; + + /* CKF_OS_LOCKING_OK is not set, and not functions supplied, + * explicit case 1 */ + if (0 == functionCount) { + *pLocking_state = SingleThreaded; + return CKR_OK; + } + + /* OS_LOCKING_OK is not set and functions have been supplied. Since + * ckfw uses nssbase library which explicitly calls NSPR, and since + * there is no way to reliably override these explicit calls to NSPR, + * therefore we can't support applications which have their own threading + * module. Return CKR_CANT_LOCK if they supplied the correct number of + * arguments, or CKR_ARGUMENTS_BAD if they did not in either case we will + * fail the initialize */ + return (4 == functionCount) ? CKR_CANT_LOCK : CKR_ARGUMENTS_BAD; +} + /* * NSSCKFWC_Initialize * @@ -155,12 +195,9 @@ NSSCKFWC_Initialize goto loser; } - /* remember the locking args for those times we need to get a lock in code - * outside the framework. - */ - error = nssSetLockArgs(pInitArgs, &locking_state); - if (CKR_OK != error) { - goto loser; + error = nssCKFW_GetThreadSafeState(pInitArgs,&locking_state); + if( CKR_OK != error ) { + goto loser; } *pFwInstance = nssCKFWInstance_Create(pInitArgs, locking_state, mdInstance, &error); diff --git a/security/nss/lib/crmf/cmmfrec.c b/security/nss/lib/crmf/cmmfrec.c index 3aa3d266d..3dd7cdd07 100644 --- a/security/nss/lib/crmf/cmmfrec.c +++ b/security/nss/lib/crmf/cmmfrec.c @@ -70,22 +70,22 @@ CMMF_DestroyKeyRecRepContent(CMMFKeyRecRepContent *inKeyRecRep) { PORT_Assert(inKeyRecRep != NULL); if (inKeyRecRep != NULL && inKeyRecRep->poolp != NULL) { - if (!inKeyRecRep->isDecoded) { - int i; + int i; + if (!inKeyRecRep->isDecoded && inKeyRecRep->newSigCert != NULL) { CERT_DestroyCertificate(inKeyRecRep->newSigCert); - if (inKeyRecRep->caCerts != NULL) { - for (i=0; inKeyRecRep->caCerts[i] != NULL; i++) { - CERT_DestroyCertificate(inKeyRecRep->caCerts[i]); - } + } + if (inKeyRecRep->caCerts != NULL) { + for (i=0; inKeyRecRep->caCerts[i] != NULL; i++) { + CERT_DestroyCertificate(inKeyRecRep->caCerts[i]); } - if (inKeyRecRep->keyPairHist != NULL) { - for (i=0; inKeyRecRep->keyPairHist[i] != NULL; i++) { - if (inKeyRecRep->keyPairHist[i]->certOrEncCert.choice == + } + if (inKeyRecRep->keyPairHist != NULL) { + for (i=0; inKeyRecRep->keyPairHist[i] != NULL; i++) { + if (inKeyRecRep->keyPairHist[i]->certOrEncCert.choice == cmmfCertificate) { - CERT_DestroyCertificate(inKeyRecRep->keyPairHist[i]-> + CERT_DestroyCertificate(inKeyRecRep->keyPairHist[i]-> certOrEncCert.cert.certificate); - } } } } @@ -117,6 +117,10 @@ CMMF_KeyRecRepContentSetNewSignCert(CMMFKeyRecRepContent *inKeyRecRep, if (inKeyRecRep == NULL || inNewSignCert == NULL) { return SECFailure; } + if (!inKeyRecRep->isDecoded && inKeyRecRep->newSigCert) { + CERT_DestroyCertificate(inKeyRecRep->newSigCert); + } + inKeyRecRep->isDecoded = PR_FALSE; inKeyRecRep->newSigCert = CERT_DupCertificate(inNewSignCert); return (inKeyRecRep->newSigCert == NULL) ? SECFailure : SECSuccess; } @@ -231,6 +235,12 @@ CMMF_KeyRecRepContentGetNewSignCert(CMMFKeyRecRepContent *inKeyRecRep) inKeyRecRep->newSigCert == NULL) { return NULL; } + /* newSigCert may not be a real certificate, it may be a hand decoded + * cert structure. This code makes sure we hand off a real, fully formed + * CERTCertificate to the caller. TODO: This should move into the decode + * portion so that we never wind up with a half formed CERTCertificate + * here. In this case the call would be to CERT_DupCertificate. + */ return CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &inKeyRecRep->newSigCert->signatureWrap.data, NULL, PR_FALSE, PR_TRUE); diff --git a/security/nss/lib/cryptohi/hasht.h b/security/nss/lib/cryptohi/hasht.h index 2d2c6b0ca..6df38b49a 100644 --- a/security/nss/lib/cryptohi/hasht.h +++ b/security/nss/lib/cryptohi/hasht.h @@ -72,13 +72,15 @@ typedef enum { * Structure to hold hash computation info and routines */ struct SECHashObjectStr { - unsigned int length; + unsigned int length; /* hash output length (in bytes) */ void * (*create)(void); void * (*clone)(void *); void (*destroy)(void *, PRBool); void (*begin)(void *); void (*update)(void *, const unsigned char *, unsigned int); void (*end)(void *, unsigned char *, unsigned int *, unsigned int); + unsigned int blocklength; /* hash input block size (in bytes) */ + HASH_HashType type; }; struct HASHContextStr { diff --git a/security/nss/lib/cryptohi/keyhi.h b/security/nss/lib/cryptohi/keyhi.h index c66edbcd7..8707c3d1d 100644 --- a/security/nss/lib/cryptohi/keyhi.h +++ b/security/nss/lib/cryptohi/keyhi.h @@ -283,9 +283,7 @@ SECKEY_AddPublicKeyToListTail( SECKEYPublicKeyList *list, #define PUBKEY_LIST_NEXT(n) ((SECKEYPublicKeyListNode *)n->links.next) #define PUBKEY_LIST_END(n,l) (((void *)n) == ((void *)&l->list)) -#ifdef NSS_ENABLE_ECC extern int SECKEY_ECParamsToKeySize(const SECItem *params); -#endif /* NSS_ENABLE_ECC */ SEC_END_PROTOS diff --git a/security/nss/lib/cryptohi/manifest.mn b/security/nss/lib/cryptohi/manifest.mn index 657302e69..897559896 100644 --- a/security/nss/lib/cryptohi/manifest.mn +++ b/security/nss/lib/cryptohi/manifest.mn @@ -65,8 +65,3 @@ LIBSRCS = \ $(NULL) CSRCS = $(LIBSRCS) - -ifdef NSS_ENABLE_ECC -DEFINES += -DNSS_ENABLE_ECC -endif - diff --git a/security/nss/lib/cryptohi/sechash.c b/security/nss/lib/cryptohi/sechash.c index e977dd5f2..eebe23d95 100644 --- a/security/nss/lib/cryptohi/sechash.c +++ b/security/nss/lib/cryptohi/sechash.c @@ -114,7 +114,9 @@ const SECHashObject SECHashObjects[] = { (void (*)(void *)) null_hash_begin, (void (*)(void *, const unsigned char *, unsigned int)) null_hash_update, (void (*)(void *, unsigned char *, unsigned int *, - unsigned int)) null_hash_end + unsigned int)) null_hash_end, + 0, + HASH_AlgNULL }, { MD2_LENGTH, (void * (*)(void)) md2_NewContext, @@ -123,7 +125,9 @@ const SECHashObject SECHashObjects[] = { (void (*)(void *)) PK11_DigestBegin, (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp, (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) - PK11_DigestFinal + PK11_DigestFinal, + MD2_BLOCK_LENGTH, + HASH_AlgMD2 }, { MD5_LENGTH, (void * (*)(void)) md5_NewContext, @@ -132,7 +136,9 @@ const SECHashObject SECHashObjects[] = { (void (*)(void *)) PK11_DigestBegin, (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp, (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) - PK11_DigestFinal + PK11_DigestFinal, + MD5_BLOCK_LENGTH, + HASH_AlgMD5 }, { SHA1_LENGTH, (void * (*)(void)) sha1_NewContext, @@ -141,7 +147,9 @@ const SECHashObject SECHashObjects[] = { (void (*)(void *)) PK11_DigestBegin, (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp, (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) - PK11_DigestFinal + PK11_DigestFinal, + SHA1_BLOCK_LENGTH, + HASH_AlgSHA1 }, { SHA256_LENGTH, (void * (*)(void)) sha256_NewContext, @@ -150,7 +158,9 @@ const SECHashObject SECHashObjects[] = { (void (*)(void *)) PK11_DigestBegin, (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp, (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) - PK11_DigestFinal + PK11_DigestFinal, + SHA256_BLOCK_LENGTH, + HASH_AlgSHA256 }, { SHA384_LENGTH, (void * (*)(void)) sha384_NewContext, @@ -159,7 +169,9 @@ const SECHashObject SECHashObjects[] = { (void (*)(void *)) PK11_DigestBegin, (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp, (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) - PK11_DigestFinal + PK11_DigestFinal, + SHA384_BLOCK_LENGTH, + HASH_AlgSHA384 }, { SHA512_LENGTH, (void * (*)(void)) sha512_NewContext, @@ -168,7 +180,9 @@ const SECHashObject SECHashObjects[] = { (void (*)(void *)) PK11_DigestBegin, (void (*)(void *, const unsigned char *, unsigned int)) PK11_DigestOp, (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) - PK11_DigestFinal + PK11_DigestFinal, + SHA512_BLOCK_LENGTH, + HASH_AlgSHA512 }, }; diff --git a/security/nss/lib/cryptohi/seckey.c b/security/nss/lib/cryptohi/seckey.c index 843ce9a26..97f79d99e 100644 --- a/security/nss/lib/cryptohi/seckey.c +++ b/security/nss/lib/cryptohi/seckey.c @@ -243,7 +243,6 @@ SECKEY_CreateDHPrivateKey(SECKEYDHParams *param, SECKEYPublicKey **pubk, void *c SECKEYPrivateKey * SECKEY_CreateECPrivateKey(SECKEYECParams *param, SECKEYPublicKey **pubk, void *cx) { -#ifdef NSS_ENABLE_ECC SECKEYPrivateKey *privk; PK11SlotInfo *slot = PK11_GetBestSlot(CKM_EC_KEY_PAIR_GEN,cx); @@ -255,9 +254,6 @@ SECKEY_CreateECPrivateKey(SECKEYECParams *param, SECKEYPublicKey **pubk, void *c PK11_FreeSlot(slot); return(privk); -#else - return NULL; -#endif /* NSS_ENABLE_ECC */ } void @@ -299,10 +295,22 @@ SECKEY_CopySubjectPublicKeyInfo(PRArenaPool *arena, CERTSubjectPublicKeyInfo *from) { SECStatus rv; + SECItem spk; rv = SECOID_CopyAlgorithmID(arena, &to->algorithm, &from->algorithm); - if (rv == SECSuccess) - rv = SECITEM_CopyItem(arena, &to->subjectPublicKey, &from->subjectPublicKey); + if (rv == SECSuccess) { + /* + * subjectPublicKey is a bit string, whose length is in bits. + * Convert the length from bits to bytes for SECITEM_CopyItem. + */ + spk = from->subjectPublicKey; + DER_ConvertBitString(&spk); + rv = SECITEM_CopyItem(arena, &to->subjectPublicKey, &spk); + /* Set the length back to bits. */ + if (rv == SECSuccess) { + to->subjectPublicKey.len = from->subjectPublicKey.len; + } + } return rv; } @@ -1093,7 +1101,6 @@ seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki) break; -#ifdef NSS_ENABLE_ECC case SEC_OID_ANSIX962_EC_PUBLIC_KEY: pubk->keyType = ecKey; pubk->u.ec.size = 0; @@ -1108,7 +1115,6 @@ seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki) rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &newOs); if (rv == SECSuccess) return pubk; break; -#endif /* NSS_ENABLE_ECC */ default: rv = SECFailure; @@ -1305,7 +1311,6 @@ SECKEY_PublicKeyStrength(SECKEYPublicKey *pubk) pubk->u.dh.publicValue.len - 1; case fortezzaKey: return PR_MAX(pubk->u.fortezza.KEAKey.len, pubk->u.fortezza.DSSKey.len); -#ifdef NSS_ENABLE_ECC case ecKey: /* Get the key size in bits and adjust */ if (pubk->u.ec.size == 0) { @@ -1313,7 +1318,6 @@ SECKEY_PublicKeyStrength(SECKEYPublicKey *pubk) SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams); } return (pubk->u.ec.size + 7)/8; -#endif /* NSS_ENABLE_ECC */ default: break; } @@ -1330,14 +1334,12 @@ SECKEY_PublicKeyStrengthInBits(SECKEYPublicKey *pubk) case dhKey: case fortezzaKey: return SECKEY_PublicKeyStrength(pubk) * 8; /* 1 byte = 8 bits */ -#ifdef NSS_ENABLE_ECC case ecKey: if (pubk->u.ec.size == 0) { pubk->u.ec.size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams); } return pubk->u.ec.size; -#endif /* NSS_ENABLE_ECC */ default: break; } @@ -1493,7 +1495,6 @@ SECKEY_CopyPublicKey(SECKEYPublicKey *pubk) rv = SECITEM_CopyItem(arena, ©k->u.dh.publicValue, &pubk->u.dh.publicValue); break; -#ifdef NSS_ENABLE_ECC case ecKey: copyk->u.ec.size = pubk->u.ec.size; rv = SECITEM_CopyItem(arena,©k->u.ec.DEREncodedParams, @@ -1502,7 +1503,6 @@ SECKEY_CopyPublicKey(SECKEYPublicKey *pubk) rv = SECITEM_CopyItem(arena,©k->u.ec.publicValue, &pubk->u.ec.publicValue); break; -#endif /* NSS_ENABLE_ECC */ case nullKey: return copyk; default: @@ -1661,7 +1661,6 @@ SECKEY_CreateSubjectPublicKeyInfo(SECKEYPublicKey *pubk) } SECITEM_FreeItem(¶ms, PR_FALSE); break; -#ifdef NSS_ENABLE_ECC case ecKey: rv = SECITEM_CopyItem(arena, ¶ms, &pubk->u.ec.DEREncodedParams); @@ -1687,7 +1686,6 @@ SECKEY_CreateSubjectPublicKeyInfo(SECKEYPublicKey *pubk) return spki; } break; -#endif /* NSS_ENABLE_ECC */ case keaKey: case dhKey: /* later... */ diff --git a/security/nss/lib/cryptohi/secsign.c b/security/nss/lib/cryptohi/secsign.c index 68447be26..12e6ed3ad 100644 --- a/security/nss/lib/cryptohi/secsign.c +++ b/security/nss/lib/cryptohi/secsign.c @@ -121,18 +121,16 @@ SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *key) signalg = SEC_OID_MISSI_DSS; /* XXX Is there a better algid? */ keyType = fortezzaKey; break; -#ifdef NSS_ENABLE_ECC case SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST: hashalg = SEC_OID_SHA1; - signalg = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST; + signalg = SEC_OID_ANSIX962_EC_PUBLIC_KEY; keyType = ecKey; break; -#endif /* NSS_ENABLE_ECC */ /* we don't implement MD4 hashes. * we *CERTAINLY* don't want to sign one! */ case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION: default: - PORT_SetError(SEC_ERROR_INVALID_ARGS); + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); return 0; } @@ -266,7 +264,7 @@ SGN_End(SGNContext *cx, SECItem *result) } if ((cx->signalg == SEC_OID_ANSIX9_DSA_SIGNATURE) || - (cx->signalg == SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST)) { + (cx->signalg == SEC_OID_ANSIX962_EC_PUBLIC_KEY)) { /* DSAU_EncodeDerSigWithLen works for DSA and ECDSA */ rv = DSAU_EncodeDerSigWithLen(result, &sigitem, signatureLen); PORT_Free(sigitem.data); @@ -319,57 +317,6 @@ SEC_SignData(SECItem *res, unsigned char *buf, int len, return rv; } -/* -** Sign the input file's contents returning in result a bunch of bytes -** that are the signature. Returns zero on success, an error code on -** failure. -*/ -SECStatus -SEC_SignFile(SECItem *result, FILE *input, - SECKEYPrivateKey *pk, SECOidTag algid) -{ - unsigned char buf[1024]; - SECStatus rv; - int nb; - SGNContext *sgn; - - sgn = SGN_NewContext(algid, pk); - if (sgn == NULL) - return SECFailure; - rv = SGN_Begin(sgn); - if (rv != SECSuccess) - goto loser; - - /* - ** Now feed the contents of the input file into the digest - ** algorithm, one chunk at a time, until we have exhausted the - ** input - */ - for (;;) { - if (feof(input)) break; - nb = fread(buf, 1, sizeof(buf), input); - if (nb == 0) { - if (ferror(input)) { - PORT_SetError(SEC_ERROR_IO); - rv = SECFailure; - goto loser; - } - break; - } - rv = SGN_Update(sgn, buf, nb); - if (rv != SECSuccess) - goto loser; - } - - /* Sign the digest */ - rv = SGN_End(sgn, result); - /* FALL THROUGH */ - - loser: - SGN_DestroyContext(sgn, PR_TRUE); - return rv; -} - /************************************************************************/ DERTemplate CERTSignedDataTemplate[] = @@ -425,14 +372,12 @@ SEC_DerSignData(PRArenaPool *arena, SECItem *result, case dsaKey: algID = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; break; -#ifdef NSS_ENABLE_ECC case ecKey: algID = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST; break; -#endif /* NSS_ENABLE_ECC */ default: + PORT_SetError(SEC_ERROR_INVALID_KEY); return SECFailure; - break; } } @@ -557,12 +502,10 @@ SEC_GetSignatureAlgorithmOidTag(KeyType keyType, SECOidTag hashAlgTag) break; } break; -#ifdef NSS_ENABLE_ECC case ecKey: /* XXX For now only ECDSA with SHA1 is supported */ sigTag = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST; break; -#endif /* NSS_ENABLE_ECC */ default: break; } diff --git a/security/nss/lib/cryptohi/secvfy.c b/security/nss/lib/cryptohi/secvfy.c index 4a5de4e0f..311bec35e 100644 --- a/security/nss/lib/cryptohi/secvfy.c +++ b/security/nss/lib/cryptohi/secvfy.c @@ -50,12 +50,14 @@ #include "secerr.h" /* -** Decrypt signature block using public key (in place) +** Decrypt signature block using public key +** Store the hash algorithm oid tag in *tagp +** Store the digest in the digest buffer ** XXX this is assuming that the signature algorithm has WITH_RSA_ENCRYPTION */ static SECStatus -DecryptSigBlock(SECOidTag *tagp, unsigned char *digest, SECKEYPublicKey *key, - SECItem *sig, char *wincx) +DecryptSigBlock(SECOidTag *tagp, unsigned char *digest, unsigned int len, + SECKEYPublicKey *key, SECItem *sig, char *wincx) { SGNDigestInfo *di = NULL; unsigned char *buf = NULL; @@ -83,7 +85,7 @@ DecryptSigBlock(SECOidTag *tagp, unsigned char *digest, SECKEYPublicKey *key, */ tag = SECOID_GetAlgorithmTag(&di->digestAlgorithm); /* XXX Check that tag is an appropriate algorithm? */ - if (di->digest.len > HASH_LENGTH_MAX) { + if (di->digest.len > len) { PORT_SetError(SEC_ERROR_OUTPUT_LEN); goto loser; } @@ -107,29 +109,45 @@ DecryptSigBlock(SECOidTag *tagp, unsigned char *digest, SECKEYPublicKey *key, typedef enum { VFY_RSA, VFY_DSA, VFY_ECDSA } VerifyType; struct VFYContextStr { - SECOidTag alg; + SECOidTag alg; /* the hash algorithm */ VerifyType type; SECKEYPublicKey *key; /* - * digest holds either the hash (<= HASH_LENGTH_MAX=64 bytes) - * in the RSA signature, or the full DSA signature (40 bytes). + * This buffer holds either the digest or the full signature + * depending on the type of the signature. It is defined as a + * union to make sure it always has enough space. + * + * Use the "buffer" union member to reference the buffer. + * Note: do not take the size of the "buffer" union member. Take + * the size of the union or some other union member instead. */ - unsigned char digest[HASH_LENGTH_MAX]; + union { + unsigned char buffer[1]; + + /* the digest in the decrypted RSA signature */ + unsigned char rsadigest[HASH_LENGTH_MAX]; + /* the full DSA signature... 40 bytes */ + unsigned char dsasig[DSA_SIGNATURE_LEN]; + /* the full ECDSA signature */ + unsigned char ecdsasig[2 * MAX_ECKEY_LEN]; + } u; void * wincx; void *hashcx; const SECHashObject *hashobj; - SECOidTag sigAlg; - PRBool hasSignature; - unsigned char ecdsadigest[2 * MAX_ECKEY_LEN]; + SECOidTag sigAlg; /* the (composite) signature algorithm */ + PRBool hasSignature; /* true if the signature was provided in the + * VFY_CreateContext call. If false, the + * signature must be provided with a + * VFY_EndWithSignature call. */ }; /* * decode the ECDSA or DSA signature from it's DER wrapping. * The unwrapped/raw signature is placed in the buffer pointed - * to by digest and has enough room for len bytes. + * to by dsig and has enough room for len bytes. */ static SECStatus -decodeECorDSASignature(SECOidTag algid, SECItem *sig, unsigned char *digest, +decodeECorDSASignature(SECOidTag algid, SECItem *sig, unsigned char *dsig, unsigned int len) { SECItem *dsasig = NULL; /* also used for ECDSA */ SECStatus rv=SECSuccess; @@ -152,14 +170,14 @@ decodeECorDSASignature(SECOidTag algid, SECItem *sig, unsigned char *digest, if ((dsasig == NULL) || (dsasig->len != len)) { rv = SECFailure; } else { - PORT_Memcpy(digest, dsasig->data, dsasig->len); + PORT_Memcpy(dsig, dsasig->data, dsasig->len); } break; default: if (sig->len != len) { rv = SECFailure; } else { - PORT_Memcpy(digest, sig->data, sig->len); + PORT_Memcpy(dsig, sig->data, sig->len); } break; } @@ -176,7 +194,9 @@ decodeECorDSASignature(SECOidTag algid, SECItem *sig, unsigned char *digest, * alg: the composite algorithm to dissect. * hashalg: address of a SECOidTag which will be set with the hash algorithm. * signalg: address of a SECOidTag which will be set with the signing alg. + * (not implemented) * keyType: address of a KeyType which will be set with the key type. + * (not implemented) * Returns: SECSuccess if the algorithm was acceptable, SECFailure if the * algorithm was not found or was not a signing algorithm. */ @@ -234,7 +254,6 @@ VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag algid, { VFYContext *cx; SECStatus rv; - unsigned char *tmp; unsigned int sigLen; cx = (VFYContext*) PORT_ZAlloc(sizeof(VFYContext)); @@ -249,8 +268,8 @@ VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag algid, cx->key = SECKEY_CopyPublicKey(key); /* extra safety precautions */ if (sig) { SECOidTag hashid = SEC_OID_UNKNOWN; - rv = DecryptSigBlock(&hashid, &cx->digest[0], - cx->key, sig, (char*)wincx); + rv = DecryptSigBlock(&hashid, cx->u.buffer, + HASH_LENGTH_MAX, cx->key, sig, (char*)wincx); cx->alg = hashid; } else { rv = decodeSigAlg(algid,&cx->alg); @@ -265,16 +284,14 @@ VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag algid, * (it depends on the key size) */ sigLen = SECKEY_PublicKeyStrength(key) * 2; - tmp = cx->ecdsadigest; } else { cx->type = VFY_DSA; sigLen = DSA_SIGNATURE_LEN; - tmp = cx->digest; } cx->alg = SEC_OID_SHA1; cx->key = SECKEY_CopyPublicKey(key); if (sig) { - rv = decodeECorDSASignature(algid,sig,tmp,sigLen); + rv = decodeECorDSASignature(algid,sig,cx->u.buffer,sigLen); } break; default: @@ -371,11 +388,10 @@ VFY_EndWithSignature(VFYContext *cx, SECItem *sig) switch (cx->type) { case VFY_DSA: case VFY_ECDSA: + dsasig.data = cx->u.buffer; if (cx->type == VFY_DSA) { - dsasig.data = cx->digest; dsasig.len = DSA_SIGNATURE_LEN; } else { - dsasig.data = cx->ecdsadigest; dsasig.len = SECKEY_PublicKeyStrength(cx->key) * 2; } if (sig) { @@ -396,14 +412,14 @@ VFY_EndWithSignature(VFYContext *cx, SECItem *sig) case VFY_RSA: if (sig) { SECOidTag hashid = SEC_OID_UNKNOWN; - rv = DecryptSigBlock(&hashid, &cx->digest[0], - cx->key, sig, (char*)cx->wincx); + rv = DecryptSigBlock(&hashid, cx->u.buffer, + HASH_LENGTH_MAX, cx->key, sig, (char*)cx->wincx); if ((rv != SECSuccess) || (hashid != cx->alg)) { PORT_SetError(SEC_ERROR_BAD_SIGNATURE); return SECFailure; } } - if (PORT_Memcmp(final, cx->digest, part)) { + if (PORT_Memcmp(final, cx->u.buffer, part)) { PORT_SetError(SEC_ERROR_BAD_SIGNATURE); return SECFailure; } @@ -434,10 +450,7 @@ VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig, { SECStatus rv; VFYContext *cx; - SECItem dsasig; -#ifdef NSS_ENABLE_ECC - SECItem ecdsasig; -#endif /* NSS_ENABLE_ECC */ + SECItem dsasig; /* also used for ECDSA */ rv = SECFailure; @@ -445,7 +458,7 @@ VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig, if (cx != NULL) { switch (key->keyType) { case rsaKey: - if (PORT_Memcmp(digest->data, cx->digest, digest->len)) { + if (PORT_Memcmp(digest->data, cx->u.buffer, digest->len)) { PORT_SetError(SEC_ERROR_BAD_SIGNATURE); } else { rv = SECSuccess; @@ -453,26 +466,21 @@ VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig, break; case fortezzaKey: case dsaKey: - dsasig.data = &cx->digest[0]; - dsasig.len = DSA_SIGNATURE_LEN; /* magic size of dsa signature */ - if (PK11_Verify(cx->key, &dsasig, digest, cx->wincx) != SECSuccess) { - PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + case ecKey: + dsasig.data = cx->u.buffer; + if (key->keyType == ecKey) { + dsasig.len = SECKEY_PublicKeyStrength(cx->key) * 2; } else { - rv = SECSuccess; + /* magic size of dsa signature */ + dsasig.len = DSA_SIGNATURE_LEN; } - break; -#ifdef NSS_ENABLE_ECC - case ecKey: - ecdsasig.data = &cx->ecdsadigest[0]; - ecdsasig.len = SECKEY_PublicKeyStrength(cx->key) * 2; - if (PK11_Verify(cx->key, &ecdsasig, digest, cx->wincx) + if (PK11_Verify(cx->key, &dsasig, digest, cx->wincx) != SECSuccess) { - PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); } else { rv = SECSuccess; } break; -#endif /* NSS_ENABLE_ECC */ default: break; } @@ -502,49 +510,3 @@ VFY_VerifyData(unsigned char *buf, int len, SECKEYPublicKey *key, VFY_DestroyContext(cx, PR_TRUE); return rv; } - -SECStatus -SEC_VerifyFile(FILE *input, SECKEYPublicKey *key, SECItem *sig, - SECOidTag algid, void *wincx) -{ - unsigned char buf[1024]; - SECStatus rv; - int nb; - VFYContext *cx; - - cx = VFY_CreateContext(key, sig, algid, wincx); - if (cx == NULL) - rv = SECFailure; - - rv = VFY_Begin(cx); - if (rv == SECSuccess) { - /* - * Now feed the contents of the input file into the digest algorithm, - * one chunk at a time, until we have exhausted the input. - */ - for (;;) { - if (feof(input)) - break; - nb = fread(buf, 1, sizeof(buf), input); - if (nb == 0) { - if (ferror(input)) { - PORT_SetError(SEC_ERROR_IO); - VFY_DestroyContext(cx, PR_TRUE); - return SECFailure; - } - break; - } - rv = VFY_Update(cx, buf, nb); - if (rv != SECSuccess) - goto loser; - } - } - - /* Verify the digest */ - rv = VFY_End(cx); - /* FALL THROUGH */ - - loser: - VFY_DestroyContext(cx, PR_TRUE); - return rv; -} diff --git a/security/nss/lib/freebl/Makefile b/security/nss/lib/freebl/Makefile index dd844160a..1805d1c5e 100644 --- a/security/nss/lib/freebl/Makefile +++ b/security/nss/lib/freebl/Makefile @@ -62,12 +62,16 @@ include $(CORE_DEPTH)/coreconf/config.mk -include config.mk +# default for all platforms +# unset this on those that have multiple freebl libraries +FREEBL_BUILD_SINGLE_SHLIB = 1 + ifdef USE_64 DEFINES += -DNSS_USE_64 endif -ifdef USE_HYBRID - DEFINES += -DNSS_USE_HYBRID +ifdef USE_ABI32_FPU + DEFINES += -DNSS_USE_ABI32_FPU endif # des.c wants _X86_ defined for intel CPUs. @@ -132,22 +136,16 @@ ifeq ($(CPU_ARCH),x86_64) ASFILES = arcfour-amd64-gas.s mpi_amd64_gas.s ASFLAGS += -march=opteron -m64 -fPIC DEFINES += -DNSS_BEVAND_ARCFOUR -DMPI_AMD64 -DMP_ASSEMBLY_MULTIPLY - MPI_SRCS += mpi_amd64.c + DEFINES += -DNSS_USE_COMBA + MPI_SRCS += mpi_amd64.c mp_comba.c endif ifeq ($(CPU_ARCH),x86) ASFILES = mpi_x86.s DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE DEFINES += -DMP_ASSEMBLY_DIV_2DX1D - USE_FP_CODE = 1 + # The floating point ECC code doesn't work on Linux x86 (bug 311432). + #ECL_USE_FP = 1 endif -ifdef NSS_ENABLE_ECC - ifdef USE_FP_CODE - #enable floating point ECC code - DEFINES += -DECL_USE_FP - ECL_SRCS += ecp_fp160.c ecp_fp192.c ecp_fp224.c ecp_fp.c - ECL_HDRS += ecp_fp.h - endif -endif # NSS_ENABLE_ECC endif # Linux ifeq ($(OS_TARGET),AIX) @@ -159,10 +157,16 @@ endif # AIX ifeq ($(OS_TARGET), HP-UX) ifneq ($(OS_TEST), ia64) -MKSHLIB += +k +vshlibunsats -u FREEBL_GetVector +e FREEBL_GetVector -ifndef FREEBL_EXTENDED_BUILD -ifdef USE_PURE_32 -# build for DA1.1 (HP PA 1.1) pure 32 bit model +# PA-RISC +ASFILES += ret_cr16.s +ifndef USE_64 + FREEBL_BUILD_SINGLE_SHLIB = + HAVE_ABI32_INT32 = 1 + HAVE_ABI32_FPU = 1 +endif +ifdef FREEBL_CHILD_BUILD +ifdef USE_ABI32_INT32 +# build for DA1.1 (HP PA 1.1) 32-bit ABI build with 32-bit arithmetic DEFINES += -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD DEFINES += -DSHA_NO_LONG_LONG # avoid 64-bit arithmetic in SHA512 else @@ -172,71 +176,159 @@ ifdef USE_64 ASFILES += hpma512.s hppa20.s DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE else -# this builds for DA2.0 (HP PA 2.0 Narrow) hybrid model +# this builds for DA2.0 (HP PA 2.0 Narrow) ABI32_FPU model # (the 32-bit ABI with 64-bit registers) using 32-bit digits MPI_SRCS += mpi_hp.c ASFILES += hpma512.s hppa20.s DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE + ARCHFLAG = -Aa +e +DA2.0 +DS2.0 endif endif endif endif endif -# Note: -xarch=v8 or v9 is now done in coreconf +# The blapi functions are defined not only in the freebl shared +# libraries but also in the shared libraries linked with loader.c +# (libsoftokn3.so and libssl3.so). We need to use GNU ld's +# -Bsymbolic option or the equivalent option for other linkers +# to bind the blapi function references in FREEBLVector vector +# (ldvector.c) to the blapi functions defined in the freebl +# shared libraries. +ifeq (,$(filter-out BSD_OS FreeBSD Linux NetBSD, $(OS_TARGET))) + MKSHLIB += -Wl,-Bsymbolic +endif + ifeq ($(OS_TARGET),SunOS) # The -R '$ORIGIN' linker option instructs this library to search for its # dependencies in the same directory where it resides. MKSHLIB += -R '$$ORIGIN' - +ifdef NS_USE_GCC + ifdef GCC_USE_GNU_LD + MKSHLIB += -Wl,-Bsymbolic,-z,now,-z,text + else + MKSHLIB += -Wl,-B,symbolic,-z,now,-z,text + endif # GCC_USE_GNU_LD +else + MKSHLIB += -B symbolic -z now -z text +endif # NS_USE_GCC + +# Sun's WorkShop defines v8, v8plus and v9 architectures. +# gcc on Solaris defines v8 and v9 "cpus". +# gcc's v9 is equivalent to Workshop's v8plus. +# gcc's -m64 is equivalent to Workshop's v9 +# We always use Sun's assembler, which uses Sun's naming convention. ifeq ($(CPU_ARCH),sparc) - ifndef NS_USE_GCC - ifdef USE_HYBRID - OS_CFLAGS += -xchip=ultra2 - endif # USE_HYBRID - endif # NS_USE_GCC - SYSV_SPARC=1 + FREEBL_BUILD_SINGLE_SHLIB= + ifdef USE_64 + HAVE_ABI64_INT = 1 + HAVE_ABI64_FPU = 1 + else + HAVE_ABI32_INT32 = 1 + HAVE_ABI32_FPU = 1 + HAVE_ABI32_INT64 = 1 + endif + SYSV_SPARC = 1 SOLARIS_AS = /usr/ccs/bin/as + #### set arch, asm, c flags ifdef NS_USE_GCC - ifdef GCC_USE_GNU_LD - MKSHLIB += -Wl,-Bsymbolic,-z,defs,-z,now,-z,text,--version-script,mapfile.Solaris - else - MKSHLIB += -Wl,-B,symbolic,-z,defs,-z,now,-z,text,-M,mapfile.Solaris - endif # GCC_USE_GNU_LD - else - MKSHLIB += -B symbolic -z defs -z now -z text -M mapfile.Solaris + ifdef USE_ABI32_INT32 + # default ARCHFLAG=-mcpu=v8 set by coreconf/sunOS5.mk + endif + ifdef USE_ABI32_INT64 + ARCHFLAG=-mcpu=v9 -Wa,-xarch=v8plus + endif + ifdef USE_ABI32_FPU + ARCHFLAG=-mcpu=v9 -Wa,-xarch=v8plus + endif # USE_ABI32_FPU + ifdef USE_ABI64_INT + # this builds for Sparc v9a pure 64-bit architecture + endif + ifdef USE_ABI64_FPU + # this builds for Sparc v9a pure 64-bit architecture + # It uses floating point, and 32-bit word size + endif + else # NS_USE_GCC + ifdef USE_ABI32_INT32 + #ARCHFLAG=-xarch=v8 set in coreconf/sunOS5.mk + endif + ifdef USE_ABI32_INT64 + # this builds for Sparc v8+a ABI32_FPU architecture, 64-bit registers, + # 32-bit ABI, it uses 64-bit words, integer arithmetic, + # no FPU (non-VIS cpus). + # These flags were suggested by the compiler group for building + # with SunStudio 10. + SOL_CFLAGS += -xO4 -xtarget=generic + ARCHFLAG = -xarch=v8plus + SOLARIS_AS_FLAGS = -xarch=v8plus -K PIC + endif + ifdef USE_ABI32_FPU + # this builds for Sparc v8+a ABI32_FPU architecture, 64-bit registers, + # 32-bit ABI, it uses FPU code, and 32-bit word size. + # these flags were determined by running cc -### -fast and copying + # the generated flag settings + SOL_CFLAGS += -D__MATHERR_ERRNO_DONTCARE -fns -fsimple=2 -fsingle + SOL_CFLAGS += -xalias_level=basic -xbuiltin=%all + SOL_CFLAGS += -xcache=64/32/4:1024/64/4 -xchip=ultra3 -xdepend + SOL_CFLAGS += -xlibmil -xmemalign=8s -xO5 + ARCHFLAG = -xarch=v8plusa + SOLARIS_AS_FLAGS = -xarch=v8plusa -K PIC + endif + ifdef USE_ABI64_INT + # this builds for Sparc v9a pure 64-bit architecture, + # no FPU (non-VIS cpus). For building with SunStudio 10. + SOL_CFLAGS += -xO4 -xtarget=generic + ARCHFLAG = -xarch=v9 + SOLARIS_AS_FLAGS = -xarch=v9 -K PIC + endif + ifdef USE_ABI64_FPU + # this builds for Sparc v9a pure 64-bit architecture + # It uses floating point, and 32-bit word size. + # See comment for USE_ABI32_FPU. + SOL_CFLAGS += -D__MATHERR_ERRNO_DONTCARE -fns -fsimple=2 -fsingle + SOL_CFLAGS += -xalias_level=basic -xbuiltin=%all + SOL_CFLAGS += -xcache=64/32/4:1024/64/4 -xchip=ultra3 -xdepend + SOL_CFLAGS += -xlibmil -xmemalign=8s -xO5 + ARCHFLAG = -xarch=v9a + SOLARIS_AS_FLAGS = -xarch=v9a -K PIC + endif endif # NS_USE_GCC - ifdef USE_PURE_32 + + ### set MP_ flags for both GCC and Sun cc + ifdef USE_ABI32_INT32 # this builds for Sparc v8 pure 32-bit architecture - DEFINES += -DMP_USE_LONG_LONG_MULTIPLY -DMP_USE_UINT_DIGIT - DEFINES += -DMP_NO_MP_WORD + DEFINES += -DMP_USE_UINT_DIGIT -DMP_ASSEMBLY_MULTIPLY + ASFILES = mpv_sparcv8x.s DEFINES += -DSHA_NO_LONG_LONG # avoid 64-bit arithmetic in SHA512 - else - ifdef USE_64 - # this builds for Sparc v9a pure 64-bit architecture - MPI_SRCS += mpi_sparc.c - ASFILES = mpv_sparcv9.s montmulfv9.s - DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_USING_MONT_MULF - DEFINES += -DMP_USE_UINT_DIGIT - SOLARIS_FLAGS = -fast -xO5 -xrestrict=%all -xchip=ultra -xarch=v9a - SOLARIS_FLAGS += -KPIC -mt - SOLARIS_AS_FLAGS = -xarch=v9a -K PIC - else - # this builds for Sparc v8+a hybrid architecture, 64-bit registers, - # 32-bit ABI - MPI_SRCS += mpi_sparc.c - ASFILES = mpv_sparcv8.s montmulfv8.s - DEFINES += -DMP_NO_MP_WORD -DMP_ASSEMBLY_MULTIPLY - DEFINES += -DMP_USING_MONT_MULF -DMP_USE_UINT_DIGIT - SOLARIS_AS_FLAGS = -xarch=v8plusa -K PIC - endif # USE_64 - endif # USE_PURE_32 - ifdef NSS_ENABLE_ECC - DEFINES += -DECL_USE_FP - ECL_SRCS += ecp_fp160.c ecp_fp192.c ecp_fp224.c ecp_fp.c - ECL_HDRS += ecp_fp.h - endif # NSS_ENABLE_ECC + endif + ifdef USE_ABI32_INT64 + # this builds for Sparc v8+a ABI32_FPU architecture, 64-bit registers, + # 32-bit ABI, it uses 64-bit words, integer arithmetic, no FPU + # best times are with no MP_ flags specified + endif + ifdef USE_ABI32_FPU + # this builds for Sparc v8+a ABI32_FPU architecture, 64-bit registers, + # 32-bit ABI, it uses FPU code, and 32-bit word size + MPI_SRCS += mpi_sparc.c + ASFILES = mpv_sparcv8.s montmulfv8.s + DEFINES += -DMP_NO_MP_WORD -DMP_USE_UINT_DIGIT -DMP_ASSEMBLY_MULTIPLY + DEFINES += -DMP_USING_MONT_MULF -DMP_MONT_USE_MP_MUL + endif + ifdef USE_ABI64_INT + # this builds for Sparc v9a pure 64-bit architecture + # best times are with no MP_ flags specified + endif + ifdef USE_ABI64_FPU + # this builds for Sparc v9a pure 64-bit architecture + # It uses floating point, and 32-bit word size + MPI_SRCS += mpi_sparc.c + ASFILES = mpv_sparcv9.s montmulfv9.s + DEFINES += -DMP_NO_MP_WORD -DMP_USE_UINT_DIGIT -DMP_ASSEMBLY_MULTIPLY + DEFINES += -DMP_USING_MONT_MULF -DMP_MONT_USE_MP_MUL + endif + + ECL_USE_FP = 1 else # Solaris for non-sparc family CPUs ifdef NS_USE_GCC @@ -249,11 +341,16 @@ else ifdef NS_USE_GCC ASFILES = arcfour-amd64-gas.s mpi_amd64_gas.s ASFLAGS += -march=opteron -m64 -fPIC + MPI_SRCS += mp_comba.c else - ASFILES = arcfour-amd64-sun.s mpi_amd64_sun.s + ASFILES = arcfour-amd64-sun.s mpi_amd64_sun.s sha-fast-amd64-sun.s + ASFILES += mp_comba_amd64_sun.s mpcpucache_amd64.s ASFLAGS += -xarch=generic64 -K PIC + SHA_SRCS = + MPCPU_SRCS = endif DEFINES += -DNSS_BEVAND_ARCFOUR -DMPI_AMD64 -DMP_ASSEMBLY_MULTIPLY + DEFINES += -DNSS_USE_COMBA MPI_SRCS += mpi_amd64.c else # Solaris x86 @@ -262,11 +359,22 @@ else DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE DEFINES += -DMP_ASSEMBLY_DIV_2DX1D ASFILES = mpi_i86pc.s + ifndef NS_USE_GCC + MPCPU_SRCS = + ASFILES += mpcpucache_x86.s + endif endif endif # Solaris for non-sparc family CPUs endif # target == SunOS -$(OBJDIR)/sysrand$(OBJ_SUFFIX): sysrand.c unix_rand.c win_rand.c mac_rand.c os2_rand.c +ifdef NSS_ENABLE_ECC + ifdef ECL_USE_FP + #enable floating point ECC code + DEFINES += -DECL_USE_FP + ECL_SRCS += ecp_fp160.c ecp_fp192.c ecp_fp224.c ecp_fp.c + ECL_HDRS += ecp_fp.h + endif +endif # NSS_ENABLE_ECC ####################################################################### # (5) Execute "global" rules. (OPTIONAL) # @@ -291,21 +399,12 @@ rijndael_tables: $(DEFINES) $(INCLUDES) $(OBJDIR)/libfreebl.a $(OBJDIR)/make_rijndael_tab -ifdef USE_PURE_32 -vpath %.h $(FREEBL_PARENT)/ecl $(FREEBL_PARENT)/mpi $(FREEBL_PARENT) -vpath %.c $(FREEBL_PARENT)/ecl $(FREEBL_PARENT)/mpi $(FREEBL_PARENT) -vpath %.S $(FREEBL_PARENT)/ecl $(FREEBL_PARENT)/mpi $(FREEBL_PARENT) -vpath %.s $(FREEBL_PARENT)/ecl $(FREEBL_PARENT)/mpi $(FREEBL_PARENT) -vpath %.asm $(FREEBL_PARENT)/ecl $(FREEBL_PARENT)/mpi $(FREEBL_PARENT) -INCLUDES += -I$(FREEBL_PARENT) -I$(FREEBL_PARENT)/mpi -I$(FREEBL_PARENT)/ecl -else vpath %.h mpi ecl vpath %.c mpi ecl vpath %.S mpi ecl vpath %.s mpi ecl vpath %.asm mpi ecl INCLUDES += -Impi -Iecl -endif DEFINES += -DMP_API_COMPATIBLE @@ -315,22 +414,26 @@ MPI_USERS = dh.c pqg.c dsa.c rsa.c ec.c MPI_OBJS = $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(MPI_SRCS:.c=$(OBJ_SUFFIX))) MPI_OBJS += $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(MPI_USERS:.c=$(OBJ_SUFFIX))) +$(MPI_OBJS): $(MPI_HDRS) + ECL_USERS = ec.c ECL_OBJS = $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(ECL_SRCS:.c=$(OBJ_SUFFIX)) $(ECL_ASM_SRCS:$(ASM_SUFFIX)=$(OBJ_SUFFIX))) ECL_OBJS += $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(ECL_USERS:.c=$(OBJ_SUFFIX))) -$(MPI_OBJS): $(MPI_HDRS) - $(ECL_OBJS): $(ECL_HDRS) + + +$(OBJDIR)/sysrand$(OBJ_SUFFIX): sysrand.c unix_rand.c win_rand.c mac_rand.c os2_rand.c + $(OBJDIR)/$(PROG_PREFIX)mpprime$(OBJ_SUFFIX): primes.c $(OBJDIR)/ldvector$(OBJ_SUFFIX) $(OBJDIR)/loader$(OBJ_SUFFIX) : loader.h ifeq ($(SYSV_SPARC),1) -$(OBJDIR)/mpv_sparcv8.o $(OBJDIR)/montmulfv8.o : $(OBJDIR)/%.o : %.s +$(OBJDIR)/mpv_sparcv8.o $(OBJDIR)/mpv_sparcv8x.o $(OBJDIR)/montmulfv8.o : $(OBJDIR)/%.o : %.s @$(MAKE_OBJDIR) $(SOLARIS_AS) -o $@ $(SOLARIS_AS_FLAGS) $< @@ -342,39 +445,100 @@ $(OBJDIR)/mpmontg.o: mpmontg.c montmulf.h endif -ifdef FREEBL_EXTENDED_BUILD +ifndef FREEBL_CHILD_BUILD + +# Parent build. This is where we decide which shared libraries to build + +ifdef FREEBL_BUILD_SINGLE_SHLIB + +################### Single shared lib stuff ######################### +SINGLE_SHLIB_DIR = $(OBJDIR)/$(OS_TARGET)_SINGLE_SHLIB +ALL_TRASH += $(SINGLE_SHLIB_DIR) + +$(SINGLE_SHLIB_DIR): + -mkdir $(SINGLE_SHLIB_DIR) + +release_md libs:: $(SINGLE_SHLIB_DIR) + $(MAKE) FREEBL_CHILD_BUILD=1 \ + OBJDIR=$(SINGLE_SHLIB_DIR) $@ +######################## common stuff ######################### + +endif + +# multiple shared libraries + +######################## ABI32_FPU stuff ######################### +ifdef HAVE_ABI32_FPU +ABI32_FPU_DIR = $(OBJDIR)/$(OS_TARGET)_ABI32_FPU +ALL_TRASH += $(ABI32_FPU_DIR) + +$(ABI32_FPU_DIR): + -mkdir $(ABI32_FPU_DIR) + +release_md libs:: $(ABI32_FPU_DIR) + $(MAKE) FREEBL_CHILD_BUILD=1 USE_ABI32_FPU=1 \ + OBJDIR=$(ABI32_FPU_DIR) $@ +endif + +######################## ABI32_INT32 stuff ######################### +ifdef HAVE_ABI32_INT32 +ABI32_INT32_DIR = $(OBJDIR)/$(OS_TARGET)_ABI32_INT32 +ALL_TRASH += $(ABI32_INT32_DIR) -PURE32DIR = $(OBJDIR)/$(OS_TARGET)pure32 -ALL_TRASH += $(PURE32DIR) +$(ABI32_INT32_DIR): + -mkdir $(ABI32_INT32_DIR) -FILES2LN = \ - $(wildcard *.tab) \ - $(wildcard mapfile.*) \ - Makefile manifest.mn config.mk +release_md libs:: $(ABI32_INT32_DIR) + $(MAKE) FREEBL_CHILD_BUILD=1 USE_ABI32_INT32=1 \ + OBJDIR=$(ABI32_INT32_DIR) $@ +endif -LINKEDFILES = $(addprefix $(PURE32DIR)/, $(FILES2LN)) +######################## ABI32_INT64 stuff ######################### +ifdef HAVE_ABI32_INT64 +ABI32_INT64_DIR = $(OBJDIR)/$(OS_TARGET)_ABI32_INT64 +ALL_TRASH += $(ABI32_INT64_DIR) -CDDIR := $(shell pwd) +$(ABI32_INT64_DIR): + -mkdir $(ABI32_INT64_DIR) -$(PURE32DIR): - -mkdir $(PURE32DIR) - -ln -s $(CDDIR)/mpi $(PURE32DIR) +release_md libs:: $(ABI32_INT64_DIR) + $(MAKE) FREEBL_CHILD_BUILD=1 USE_ABI32_INT64=1\ + OBJDIR=$(ABI32_INT64_DIR) $@ +endif -$(LINKEDFILES) : $(PURE32DIR)/% : % - ln -s $(CDDIR)/$* $(PURE32DIR) +######################## END of 32-bit stuff ######################### -libs:: - $(MAKE) FREEBL_RECURSIVE_BUILD=1 USE_HYBRID=1 libs +# above is 32-bit builds, below is 64-bit builds -libs:: $(PURE32DIR) $(LINKEDFILES) - cd $(PURE32DIR) && $(MAKE) FREEBL_RECURSIVE_BUILD=1 USE_PURE_32=1 FREEBL_PARENT=$(CDDIR) CORE_DEPTH=$(CDDIR)/$(CORE_DEPTH) libs +######################## ABI64_FPU stuff ######################### +ifdef HAVE_ABI64_FPU +ABI64_FPU_DIR = $(OBJDIR)/$(OS_TARGET)_ABI64_FPU +ALL_TRASH += $(ABI64_FPU_DIR) -release_md:: - $(MAKE) FREEBL_RECURSIVE_BUILD=1 USE_HYBRID=1 $@ - cd $(PURE32DIR) && $(MAKE) FREEBL_RECURSIVE_BUILD=1 USE_PURE_32=1 FREEBL_PARENT=$(CDDIR) CORE_DEPTH=$(CDDIR)/$(CORE_DEPTH) $@ +$(ABI64_FPU_DIR): + -mkdir $(ABI64_FPU_DIR) +release_md libs:: $(ABI64_FPU_DIR) + $(MAKE) FREEBL_CHILD_BUILD=1 USE_ABI64_FPU=1 \ + OBJDIR=$(ABI64_FPU_DIR) $@ endif +######################## ABI64_INT stuff ######################### +ifdef HAVE_ABI64_INT +ABI64_INT_DIR = $(OBJDIR)/$(OS_TARGET)_ABI64_INT +ALL_TRASH += $(ABI64_INT_DIR) + +$(ABI64_INT_DIR): + -mkdir $(ABI64_INT_DIR) + +release_md libs:: $(ABI64_INT_DIR) + $(MAKE) FREEBL_CHILD_BUILD=1 USE_ABI64_INT=1 \ + OBJDIR=$(ABI64_INT_DIR) $@ +endif + +endif # FREEBL_CHILD_BUILD + + # Bugzilla Bug 209827: disable optimization to work around what appears # to be a VACPP optimizer bug. ifdef XP_OS2_VACPP diff --git a/security/nss/lib/freebl/aeskeywrap.c b/security/nss/lib/freebl/aeskeywrap.c index ad7d01b27..c61a94a4d 100644 --- a/security/nss/lib/freebl/aeskeywrap.c +++ b/security/nss/lib/freebl/aeskeywrap.c @@ -50,11 +50,11 @@ #include "secport.h" /* for PORT_XXX */ #include "secerr.h" #include "blapi.h" /* for AES_ functions */ - +#include "rijndael.h" struct AESKeyWrapContextStr { - AESContext * aescx; unsigned char iv[AES_KEY_WRAP_IV_BYTES]; + AESContext aescx; }; /******************************************/ @@ -62,6 +62,37 @@ struct AESKeyWrapContextStr { ** AES key wrap algorithm, RFC 3394 */ +AESKeyWrapContext * +AESKeyWrap_AllocateContext(void) +{ + AESKeyWrapContext * cx = PORT_New(AESKeyWrapContext); + return cx; +} + +SECStatus +AESKeyWrap_InitContext(AESKeyWrapContext *cx, + const unsigned char *key, + unsigned int keylen, + const unsigned char *iv, + int x1, + unsigned int encrypt, + unsigned int x2) +{ + SECStatus rv = SECFailure; + if (!cx) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (iv) { + memcpy(cx->iv, iv, sizeof cx->iv); + } else { + memset(cx->iv, 0xA6, sizeof cx->iv); + } + rv = AES_InitContext(&cx->aescx, key, keylen, NULL, NSS_AES, encrypt, + AES_BLOCK_SIZE); + return rv; +} + /* ** Create a new AES context suitable for AES encryption/decryption. ** "key" raw key data @@ -71,19 +102,14 @@ extern AESKeyWrapContext * AESKeyWrap_CreateContext(const unsigned char *key, const unsigned char *iv, int encrypt, unsigned int keylen) { - AESKeyWrapContext * cx = PORT_ZNew(AESKeyWrapContext); + SECStatus rv; + AESKeyWrapContext * cx = AESKeyWrap_AllocateContext(); if (!cx) return NULL; /* error is already set */ - cx->aescx = AES_CreateContext(key, NULL, NSS_AES, encrypt, keylen, - AES_BLOCK_SIZE); - if (!cx->aescx) { + rv = AESKeyWrap_InitContext(cx, key, keylen, iv, 0, encrypt, 0); + if (rv != SECSuccess) { PORT_Free(cx); - return NULL; /* error should already be set */ - } - if (iv) { - memcpy(cx->iv, iv, AES_KEY_WRAP_IV_BYTES); - } else { - memset(cx->iv, 0xA6, AES_KEY_WRAP_IV_BYTES); + cx = NULL; /* error should already be set */ } return cx; } @@ -97,9 +123,8 @@ extern void AESKeyWrap_DestroyContext(AESKeyWrapContext *cx, PRBool freeit) { if (cx) { - if (cx->aescx) - AES_DestroyContext(cx->aescx, PR_TRUE); - memset(cx, 0, sizeof *cx); + AES_DestroyContext(&cx->aescx, PR_FALSE); +/* memset(cx, 0, sizeof *cx); */ if (freeit) PORT_Free(cx); } @@ -253,7 +278,7 @@ AESKeyWrap_Encrypt(AESKeyWrapContext *cx, unsigned char *output, for (j = 0; j < 6; ++j) { for (i = 1; i <= nBlocks; ++i) { B[1] = R[i]; - s = AES_Encrypt(cx->aescx, (unsigned char *)B, &aesLen, + s = AES_Encrypt(&cx->aescx, (unsigned char *)B, &aesLen, sizeof B, (unsigned char *)B, sizeof B); if (s != SECSuccess) break; @@ -358,7 +383,7 @@ AESKeyWrap_Decrypt(AESKeyWrapContext *cx, unsigned char *output, xor_and_decrement((unsigned char *)&A, (unsigned char *)&t); #endif B[1] = R[i]; - s = AES_Decrypt(cx->aescx, (unsigned char *)B, &aesLen, + s = AES_Decrypt(&cx->aescx, (unsigned char *)B, &aesLen, sizeof B, (unsigned char *)B, sizeof B); if (s != SECSuccess) break; diff --git a/security/nss/lib/freebl/alg2268.c b/security/nss/lib/freebl/alg2268.c index bf8b6f357..dcc5418dc 100644 --- a/security/nss/lib/freebl/alg2268.c +++ b/security/nss/lib/freebl/alg2268.c @@ -36,7 +36,6 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -/* $Id$ */ /* $Id$ */ @@ -132,22 +131,15 @@ static const PRUint8 S[256] = { 0305,0363,0333,0107,0345,0245,0234,0167,0012,0246,0040,0150,0376,0177,0301,0255 }; -/* -** Create a new RC2 context suitable for RC2 encryption/decryption. -** "key" raw key data -** "len" the number of bytes of key data -** "iv" is the CBC initialization vector (if mode is NSS_RC2_CBC) -** "mode" one of NSS_RC2 or NSS_RC2_CBC -** "effectiveKeyLen" in bytes, not bits. -** -** When mode is set to NSS_RC2_CBC the RC2 cipher is run in "cipher block -** chaining" mode. -*/ -RC2Context * -RC2_CreateContext(const unsigned char *key, unsigned int len, - const unsigned char *input, int mode, unsigned efLen8) +RC2Context * RC2_AllocateContext(void) +{ + return PORT_ZNew(RC2Context); +} +SECStatus +RC2_InitContext(RC2Context *cx, const unsigned char *key, unsigned int len, + const unsigned char *input, int mode, unsigned int efLen8, + unsigned int unused) { - RC2Context *cx; PRUint8 *L,*L2; int i; #if !defined(IS_LITTLE_ENDIAN) @@ -155,23 +147,23 @@ RC2_CreateContext(const unsigned char *key, unsigned int len, #endif PRUint8 tmpB; - if (!key || len == 0 || len > (sizeof cx->B) || efLen8 > (sizeof cx->B)) { - return NULL; + if (!key || !cx || !len || len > (sizeof cx->B) || + efLen8 > (sizeof cx->B)) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; } if (mode == NSS_RC2) { /* groovy */ } else if (mode == NSS_RC2_CBC) { if (!input) { - return NULL; /* not groovy */ + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; } } else { - return NULL; + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; } - cx = PORT_ZNew(RC2Context); - if (!cx) - return cx; - if (mode == NSS_RC2_CBC) { cx->enc = & rc2_EncryptCBC; cx->dec = & rc2_DecryptCBC; @@ -208,6 +200,32 @@ RC2_CreateContext(const unsigned char *key, unsigned int len, SWAPK(i); /* candidate for unrolling */ } #endif + return SECSuccess; +} + +/* +** Create a new RC2 context suitable for RC2 encryption/decryption. +** "key" raw key data +** "len" the number of bytes of key data +** "iv" is the CBC initialization vector (if mode is NSS_RC2_CBC) +** "mode" one of NSS_RC2 or NSS_RC2_CBC +** "effectiveKeyLen" in bytes, not bits. +** +** When mode is set to NSS_RC2_CBC the RC2 cipher is run in "cipher block +** chaining" mode. +*/ +RC2Context * +RC2_CreateContext(const unsigned char *key, unsigned int len, + const unsigned char *iv, int mode, unsigned efLen8) +{ + RC2Context *cx = PORT_ZNew(RC2Context); + if (cx) { + SECStatus rv = RC2_InitContext(cx, key, len, iv, mode, efLen8, 0); + if (rv != SECSuccess) { + RC2_DestroyContext(cx, PR_TRUE); + cx = NULL; + } + } return cx; } diff --git a/security/nss/lib/softoken/alghmac.c b/security/nss/lib/freebl/alghmac.c index a6af07beb..b1174f460 100644 --- a/security/nss/lib/softoken/alghmac.c +++ b/security/nss/lib/freebl/alghmac.c @@ -34,66 +34,74 @@ * * ***** END LICENSE BLOCK ***** */ -#include "sechash.h" #include "secport.h" +#include "hasht.h" +#include "blapit.h" #include "alghmac.h" #include "secerr.h" -#define HMAC_PAD_SIZE 64 +#define HMAC_PAD_SIZE HASH_BLOCK_LENGTH_MAX struct HMACContextStr { void *hash; const SECHashObject *hashobj; + PRBool wasAllocated; unsigned char ipad[HMAC_PAD_SIZE]; unsigned char opad[HMAC_PAD_SIZE]; }; void -HMAC_Destroy(HMACContext *cx) +HMAC_Destroy(HMACContext *cx, PRBool freeit) { if (cx == NULL) return; - if (cx->hash != NULL) + PORT_Assert(!freeit == !cx->wasAllocated); + if (cx->hash != NULL) { cx->hashobj->destroy(cx->hash, PR_TRUE); - PORT_ZFree(cx, sizeof(HMACContext)); + PORT_Memset(cx, 0, sizeof *cx); + } + if (freeit) + PORT_Free(cx); } -HMACContext * -HMAC_Create(const SECHashObject *hash_obj, const unsigned char *secret, - unsigned int secret_len, PRBool isFIPS) +SECStatus +HMAC_Init( HMACContext * cx, const SECHashObject *hash_obj, + const unsigned char *secret, unsigned int secret_len, PRBool isFIPS) { - HMACContext *cx; unsigned int i; unsigned char hashed_secret[HASH_LENGTH_MAX]; /* required by FIPS 198 Section 3 */ if (isFIPS && secret_len < hash_obj->length/2) { PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; + return SECFailure; } - cx = (HMACContext*)PORT_ZAlloc(sizeof(HMACContext)); - if (cx == NULL) - return NULL; + if (cx == NULL) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + cx->wasAllocated = PR_FALSE; cx->hashobj = hash_obj; - cx->hash = cx->hashobj->create(); if (cx->hash == NULL) goto loser; - if (secret_len > HMAC_PAD_SIZE) { + if (secret_len > cx->hashobj->blocklength) { cx->hashobj->begin( cx->hash); cx->hashobj->update(cx->hash, secret, secret_len); PORT_Assert(cx->hashobj->length <= sizeof hashed_secret); cx->hashobj->end( cx->hash, hashed_secret, &secret_len, sizeof hashed_secret); - if (secret_len != cx->hashobj->length) + if (secret_len != cx->hashobj->length) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); goto loser; + } secret = (const unsigned char *)&hashed_secret[0]; } - PORT_Memset(cx->ipad, 0x36, sizeof cx->ipad); - PORT_Memset(cx->opad, 0x5c, sizeof cx->opad); + PORT_Memset(cx->ipad, 0x36, cx->hashobj->blocklength); + PORT_Memset(cx->opad, 0x5c, cx->hashobj->blocklength); /* fold secret into padding */ for (i = 0; i < secret_len; i++) { @@ -101,12 +109,30 @@ HMAC_Create(const SECHashObject *hash_obj, const unsigned char *secret, cx->opad[i] ^= secret[i]; } PORT_Memset(hashed_secret, 0, sizeof hashed_secret); - return cx; + return SECSuccess; loser: PORT_Memset(hashed_secret, 0, sizeof hashed_secret); - HMAC_Destroy(cx); - return NULL; + if (cx->hash != NULL) + cx->hashobj->destroy(cx->hash, PR_TRUE); + return SECFailure; +} + +HMACContext * +HMAC_Create(const SECHashObject *hash_obj, const unsigned char *secret, + unsigned int secret_len, PRBool isFIPS) +{ + SECStatus rv; + HMACContext * cx = PORT_ZNew(HMACContext); + if (cx == NULL) + return NULL; + rv = HMAC_Init(cx, hash_obj, secret, secret_len, isFIPS); + cx->wasAllocated = PR_TRUE; + if (rv != SECSuccess) { + PORT_Free(cx); /* contains no secret info */ + cx = NULL; + } + return cx; } void @@ -114,7 +140,7 @@ HMAC_Begin(HMACContext *cx) { /* start inner hash */ cx->hashobj->begin(cx->hash); - cx->hashobj->update(cx->hash, cx->ipad, sizeof(cx->ipad)); + cx->hashobj->update(cx->hash, cx->ipad, cx->hashobj->blocklength); } void @@ -137,7 +163,7 @@ HMAC_Finish(HMACContext *cx, unsigned char *result, unsigned int *result_len, return SECFailure; cx->hashobj->begin(cx->hash); - cx->hashobj->update(cx->hash, cx->opad, sizeof(cx->opad)); + cx->hashobj->update(cx->hash, cx->opad, cx->hashobj->blocklength); cx->hashobj->update(cx->hash, result, *result_len); cx->hashobj->end(cx->hash, result, result_len, max_result_len); return SECSuccess; @@ -152,15 +178,16 @@ HMAC_Clone(HMACContext *cx) if (newcx == NULL) goto loser; + newcx->wasAllocated = PR_TRUE; newcx->hashobj = cx->hashobj; newcx->hash = cx->hashobj->clone(cx->hash); if (newcx->hash == NULL) goto loser; - PORT_Memcpy(newcx->ipad, cx->ipad, sizeof(cx->ipad)); - PORT_Memcpy(newcx->opad, cx->opad, sizeof(cx->opad)); + PORT_Memcpy(newcx->ipad, cx->ipad, cx->hashobj->blocklength); + PORT_Memcpy(newcx->opad, cx->opad, cx->hashobj->blocklength); return newcx; loser: - HMAC_Destroy(newcx); + HMAC_Destroy(newcx, PR_TRUE); return NULL; } diff --git a/security/nss/lib/softoken/alghmac.h b/security/nss/lib/freebl/alghmac.h index 77c674746..81c5bfa50 100644 --- a/security/nss/lib/softoken/alghmac.h +++ b/security/nss/lib/freebl/alghmac.h @@ -43,10 +43,10 @@ SEC_BEGIN_PROTOS /* destroy HMAC context */ extern void -HMAC_Destroy(HMACContext *cx); +HMAC_Destroy(HMACContext *cx, PRBool freeit); /* create HMAC context - * hashObj hash object from SECRawHashObjects[] + * hash_obj hash object from SECRawHashObjects[] * secret the secret with which the HMAC is performed. * secret_len the length of the secret. * isFIPS true if conforming to FIPS 198. @@ -54,9 +54,14 @@ HMAC_Destroy(HMACContext *cx); * NULL is returned if an error occurs. */ extern HMACContext * -HMAC_Create(const SECHashObject *hashObj, const unsigned char *secret, +HMAC_Create(const SECHashObject *hash_obj, const unsigned char *secret, unsigned int secret_len, PRBool isFIPS); +/* like HMAC_Create, except caller allocates HMACContext. */ +SECStatus +HMAC_Init(HMACContext *cx, const SECHashObject *hash_obj, + const unsigned char *secret, unsigned int secret_len, PRBool isFIPS); + /* reset HMAC for a fresh round */ extern void HMAC_Begin(HMACContext *cx); diff --git a/security/nss/lib/freebl/arcfour-amd64-gas.s b/security/nss/lib/freebl/arcfour-amd64-gas.s index 66daf07ba..e131fd16a 100644 --- a/security/nss/lib/freebl/arcfour-amd64-gas.s +++ b/security/nss/lib/freebl/arcfour-amd64-gas.s @@ -114,3 +114,7 @@ ARCFOUR: ret .L_ARCFOUR_end: .size ARCFOUR,.L_ARCFOUR_end-ARCFOUR + +# Magic indicating no need for an executable stack +.section .note.GNU-stack,"",@progbits +.previous diff --git a/security/nss/lib/freebl/arcfour.c b/security/nss/lib/freebl/arcfour.c index 4601ace65..52329beda 100644 --- a/security/nss/lib/freebl/arcfour.c +++ b/security/nss/lib/freebl/arcfour.c @@ -64,7 +64,7 @@ #define WORD ARC4WORD #endif -#if defined(NSS_USE_HYBRID) && !defined(SOLARIS) && !defined(NSS_USE_64) +#if defined(IS_64) && !defined(__sparc) && !defined(NSS_USE_64) typedef unsigned long long WORD; #else typedef unsigned long WORD; @@ -140,28 +140,30 @@ static const Stype Kinit[256] = { 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; -/* - * Initialize a new generator. - */ RC4Context * -RC4_CreateContext(const unsigned char *key, int len) +RC4_AllocateContext(void) +{ + return PORT_ZNew(RC4Context); +} + +SECStatus +RC4_InitContext(RC4Context *cx, const unsigned char *key, unsigned int len, + const unsigned char * unused1, int unused2, + unsigned int unused3, unsigned int unused4) { int i; PRUint8 j, tmp; - RC4Context *cx; PRUint8 K[256]; PRUint8 *L; /* verify the key length. */ PORT_Assert(len > 0 && len < ARCFOUR_STATE_SIZE); if (len < 0 || len >= ARCFOUR_STATE_SIZE) { PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; + return SECFailure; } - /* Create space for the context. */ - cx = (RC4Context *)PORT_ZAlloc(sizeof(RC4Context)); if (cx == NULL) { - PORT_SetError(PR_OUT_OF_MEMORY_ERROR); - return NULL; + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; } /* Initialize the state using array indices. */ memcpy(cx->S, Kinit, sizeof cx->S); @@ -185,7 +187,25 @@ RC4_CreateContext(const unsigned char *key, int len) } cx->i = 0; cx->j = 0; - return cx; + return SECSuccess; +} + + +/* + * Initialize a new generator. + */ +RC4Context * +RC4_CreateContext(const unsigned char *key, int len) +{ + RC4Context *cx = RC4_AllocateContext(); + if (cx) { + SECStatus rv = RC4_InitContext(cx, key, len, NULL, 0, 0, 0); + if (rv != SECSuccess) { + PORT_ZFree(cx, sizeof(*cx)); + cx = NULL; + } + } + return cx; } void @@ -331,7 +351,7 @@ rc4_unrolled(RC4Context *cx, unsigned char *output, ARCFOUR_NEXT_BYTE(); streamWord |= (WORD)cx->S[t] << (n ); #endif -#if (defined(NSS_USE_HYBRID) && !defined(SOLARIS)) || defined(NSS_USE_64) +#if (defined(IS_64) && !defined(__sparc)) || defined(NSS_USE_64) /* 64-bit wordsize */ #ifdef IS_LITTLE_ENDIAN #define ARCFOUR_NEXT_WORD() \ diff --git a/security/nss/lib/freebl/blapi.h b/security/nss/lib/freebl/blapi.h index cdc8b9cb5..899eadd45 100644 --- a/security/nss/lib/freebl/blapi.h +++ b/security/nss/lib/freebl/blapi.h @@ -43,7 +43,8 @@ #define _BLAPI_H_ #include "blapit.h" - +#include "hasht.h" +#include "alghmac.h" SEC_BEGIN_PROTOS @@ -207,7 +208,7 @@ extern SECStatus EC_NewKeyFromSeed(ECParams * params, int seedlen); /* Validates an EC public key as described in Section 5.2.2 of - * X9.63. Such validation prevents against small subgroup attacks + * X9.62. Such validation prevents against small subgroup attacks * when the ECDH primitive is used with the cofactor. */ extern SECStatus EC_ValidatePublicKey(ECParams * params, @@ -267,6 +268,15 @@ extern SECStatus ECDSA_SignDigestWithSeed(ECPrivateKey *key, */ extern RC4Context *RC4_CreateContext(const unsigned char *key, int len); +extern RC4Context *RC4_AllocateContext(void); +extern SECStatus RC4_InitContext(RC4Context *cx, + const unsigned char *key, + unsigned int keylen, + const unsigned char *, + int, + unsigned int , + unsigned int ); + /* ** Destroy an RC4 encryption/decryption context. ** "cx" the context @@ -324,6 +334,14 @@ extern SECStatus RC4_Decrypt(RC4Context *cx, unsigned char *output, extern RC2Context *RC2_CreateContext(const unsigned char *key, unsigned int len, const unsigned char *iv, int mode, unsigned effectiveKeyLen); +extern RC2Context *RC2_AllocateContext(void); +extern SECStatus RC2_InitContext(RC2Context *cx, + const unsigned char *key, + unsigned int keylen, + const unsigned char *iv, + int mode, + unsigned int effectiveKeyLen, + unsigned int ); /* ** Destroy an RC2 encryption/decryption context. @@ -379,6 +397,14 @@ extern SECStatus RC2_Decrypt(RC2Context *cx, unsigned char *output, */ extern RC5Context *RC5_CreateContext(const SECItem *key, unsigned int rounds, unsigned int wordSize, const unsigned char *iv, int mode); +extern RC5Context *RC5_AllocateContext(void); +extern SECStatus RC5_InitContext(RC5Context *cx, + const unsigned char *key, + unsigned int keylen, + const unsigned char *iv, + int mode, + unsigned int rounds, + unsigned int wordSize); /* ** Destroy an RC5 encryption/decryption context. @@ -440,6 +466,14 @@ extern SECStatus RC5_Decrypt(RC5Context *cx, unsigned char *output, extern DESContext *DES_CreateContext(const unsigned char *key, const unsigned char *iv, int mode, PRBool encrypt); +extern DESContext *DES_AllocateContext(void); +extern SECStatus DES_InitContext(DESContext *cx, + const unsigned char *key, + unsigned int keylen, + const unsigned char *iv, + int mode, + unsigned int encrypt, + unsigned int ); /* ** Destroy an DES encryption/decryption context. @@ -498,6 +532,14 @@ extern AESContext * AES_CreateContext(const unsigned char *key, const unsigned char *iv, int mode, int encrypt, unsigned int keylen, unsigned int blocklen); +extern AESContext *AES_AllocateContext(void); +extern SECStatus AES_InitContext(AESContext *cx, + const unsigned char *key, + unsigned int keylen, + const unsigned char *iv, + int mode, + unsigned int encrypt, + unsigned int blocklen); /* ** Destroy a AES encryption/decryption context. @@ -554,6 +596,15 @@ AES_Decrypt(AESContext *cx, unsigned char *output, extern AESKeyWrapContext * AESKeyWrap_CreateContext(const unsigned char *key, const unsigned char *iv, int encrypt, unsigned int keylen); +extern AESKeyWrapContext * AESKeyWrap_AllocateContext(void); +extern SECStatus + AESKeyWrap_InitContext(AESKeyWrapContext *cx, + const unsigned char *key, + unsigned int keylen, + const unsigned char *iv, + int , + unsigned int encrypt, + unsigned int ); /* ** Destroy a AES KeyWrap context. @@ -649,6 +700,7 @@ extern void MD5_Update(MD5Context *cx, */ extern void MD5_End(MD5Context *cx, unsigned char *digest, unsigned int *digestLen, unsigned int maxDigestLen); + /* * Return the the size of a buffer needed to flatten the MD5 Context into * "cx" the context @@ -671,6 +723,7 @@ extern SECStatus MD5_Flatten(MD5Context *cx,unsigned char *space); * returns resurected context; */ extern MD5Context * MD5_Resurrect(unsigned char *space, void *arg); +extern void MD5_Clone(MD5Context *dest, MD5Context *src); /* ** trace the intermediate state info of the MD5 hash. @@ -748,6 +801,7 @@ extern SECStatus MD2_Flatten(MD2Context *cx,unsigned char *space); * returns resurected context; */ extern MD2Context * MD2_Resurrect(unsigned char *space, void *arg); +extern void MD2_Clone(MD2Context *dest, MD2Context *src); /******************************************/ /* @@ -830,6 +884,7 @@ extern SECStatus SHA1_Flatten(SHA1Context *cx,unsigned char *space); * returns resurected context; */ extern SHA1Context * SHA1_Resurrect(unsigned char *space, void *arg); +extern void SHA1_Clone(SHA1Context *dest, SHA1Context *src); /******************************************/ @@ -847,6 +902,7 @@ extern void SHA256_TraceState(SHA256Context *cx); extern unsigned int SHA256_FlattenSize(SHA256Context *cx); extern SECStatus SHA256_Flatten(SHA256Context *cx,unsigned char *space); extern SHA256Context * SHA256_Resurrect(unsigned char *space, void *arg); +extern void SHA256_Clone(SHA256Context *dest, SHA256Context *src); /******************************************/ @@ -864,6 +920,7 @@ extern void SHA512_TraceState(SHA512Context *cx); extern unsigned int SHA512_FlattenSize(SHA512Context *cx); extern SECStatus SHA512_Flatten(SHA512Context *cx,unsigned char *space); extern SHA512Context * SHA512_Resurrect(unsigned char *space, void *arg); +extern void SHA512_Clone(SHA512Context *dest, SHA512Context *src); /******************************************/ @@ -881,6 +938,15 @@ extern void SHA384_TraceState(SHA384Context *cx); extern unsigned int SHA384_FlattenSize(SHA384Context *cx); extern SECStatus SHA384_Flatten(SHA384Context *cx,unsigned char *space); extern SHA384Context * SHA384_Resurrect(unsigned char *space, void *arg); +extern void SHA384_Clone(SHA384Context *dest, SHA384Context *src); + +/**************************************** + * implement TLS Pseudo Random Function (PRF) + */ + +extern SECStatus +TLS_PRF(const SECItem *secret, const char *label, SECItem *seed, + SECItem *result, PRBool isFIPS); /******************************************/ /* @@ -916,6 +982,7 @@ extern SECStatus RNG_GenerateGlobalRandomBytes(void *dest, size_t len); */ extern void RNG_RNGShutdown(void); +extern void RNG_SystemInfoForRNG(void); /* Generate PQGParams and PQGVerify structs. * Length of seed and length of h both equal length of P. @@ -987,6 +1054,9 @@ PRBool BLAPI_SHVerify(const char *name, PRFuncPtr addr); **************************************************************************/ PRBool BLAPI_VerifySelf(const char *name); +/*********************************************************************/ +extern const SECHashObject * HASH_GetRawHashObject(HASH_HashType hashType); + SEC_END_PROTOS #endif /* _BLAPI_H_ */ diff --git a/security/nss/lib/freebl/blapit.h b/security/nss/lib/freebl/blapit.h index 36aa8db82..2400ce325 100644 --- a/security/nss/lib/freebl/blapit.h +++ b/security/nss/lib/freebl/blapit.h @@ -95,9 +95,13 @@ * Input block size for each hash algorithm. */ +#define MD2_BLOCK_LENGTH 64 /* bytes */ +#define MD5_BLOCK_LENGTH 64 /* bytes */ +#define SHA1_BLOCK_LENGTH 64 /* bytes */ #define SHA256_BLOCK_LENGTH 64 /* bytes */ #define SHA384_BLOCK_LENGTH 128 /* bytes */ #define SHA512_BLOCK_LENGTH 128 /* bytes */ +#define HASH_BLOCK_LENGTH_MAX SHA512_BLOCK_LENGTH #define AES_KEY_WRAP_IV_BYTES 8 #define AES_KEY_WRAP_BLOCK_SIZE 8 /* bytes */ @@ -146,7 +150,9 @@ * function takes desired number of bits in P, * returns index (0..8) or -1 if number of bits is invalid. */ -#define PQG_PBITS_TO_INDEX(bits) ((((bits)-512) % 64) ? -1 : (int)((bits)-512)/64) +#define PQG_PBITS_TO_INDEX(bits) \ + (((bits) < 512 || (bits) > 1024 || (bits) % 64) ? \ + -1 : (int)((bits)-512)/64) /* * function takes index (0-8) @@ -348,4 +354,19 @@ struct ECPrivateKeyStr { }; typedef struct ECPrivateKeyStr ECPrivateKey; +typedef void * (*BLapiAllocateFunc)(void); +typedef void (*BLapiDestroyContextFunc)(void *cx, PRBool freeit); +typedef SECStatus (*BLapiInitContextFunc)(void *cx, + const unsigned char *key, + unsigned int keylen, + const unsigned char *, + int, + unsigned int , + unsigned int ); +typedef SECStatus (*BLapiEncrypt)(void *cx, unsigned char *output, + unsigned int *outputLen, + unsigned int maxOutputLen, + const unsigned char *input, + unsigned int inputLen); + #endif /* _BLAPIT_H_ */ diff --git a/security/nss/lib/freebl/config.mk b/security/nss/lib/freebl/config.mk index c5e5b0d3b..ecbc9373f 100644 --- a/security/nss/lib/freebl/config.mk +++ b/security/nss/lib/freebl/config.mk @@ -36,38 +36,21 @@ # ***** END LICENSE BLOCK ***** # only do this in the outermost freebl build. -ifndef FREEBL_RECURSIVE_BUILD -# we only do this stuff for some of the 32-bit builds, no 64-bit builds -ifndef USE_64 - -ifeq ($(OS_TARGET), HP-UX) - ifneq ($(OS_TEST), ia64) - FREEBL_EXTENDED_BUILD = 1 - endif -endif - -ifeq ($(OS_TARGET),SunOS) - ifeq ($(CPU_ARCH),sparc) - FREEBL_EXTENDED_BUILD = 1 - endif -endif +ifndef FREEBL_CHILD_BUILD -ifdef FREEBL_EXTENDED_BUILD # We're going to change this build so that it builds libfreebl.a with # just loader.c. Then we have to build this directory twice again to # build the two DSOs. # To build libfreebl.a with just loader.c, we must now override many # of the make variables setup by the prior inclusion of CORECONF's config.mk -CSRCS = loader.c sysrand.c +CSRCS = loader.c SIMPLE_OBJS = $(CSRCS:.c=$(OBJ_SUFFIX)) OBJS = $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(SIMPLE_OBJS)) ALL_TRASH := $(TARGETS) $(OBJS) $(OBJDIR) LOGS TAGS $(GARBAGE) \ $(NOSUCHFILE) so_locations -endif -#end of 32-bit only stuff. -endif +# this is not a recursive child make. We make a static lib. (archive) # Override the values defined in coreconf's ruleset.mk. # @@ -83,25 +66,47 @@ endif PROGRAM = else -# This is a recursive build. +# This is a recursive child make. We build the shared lib. -TARGETS = $(SHARED_LIBRARY) +TARGETS = $(SHARED_LIBRARY) LIBRARY = +IMPORT_LIBRARY = PROGRAM = -#ifeq ($(OS_TARGET), HP-UX) - EXTRA_LIBS += \ - $(DIST)/lib/libsecutil.$(LIB_SUFFIX) \ +EXTRA_LIBS += $(DIST)/lib/$(LIB_PREFIX)secutil.$(LIB_SUFFIX) + +ifeq (,$(filter-out WIN%,$(OS_TARGET))) + +# don't want the 32 in the shared library name +SHARED_LIBRARY = $(OBJDIR)/$(DLL_PREFIX)$(LIBRARY_NAME)$(LIBRARY_VERSION).$(DLL_SUFFIX) + +RES = $(OBJDIR)/$(LIBRARY_NAME).res +RESNAME = freebl.rc + +ifdef NS_USE_GCC +EXTRA_SHARED_LIBS += \ + -L$(NSPR_LIB_DIR) \ + -lplc4 \ + -lplds4 \ + -lnspr4 \ $(NULL) +else # ! NS_USE_GCC +EXTRA_SHARED_LIBS += \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \ + $(NULL) +endif # NS_USE_GCC -# $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS) -# $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX. - EXTRA_SHARED_LIBS += \ - -L$(DIST)/lib/ \ +else + +EXTRA_SHARED_LIBS += \ + -L$(NSPR_LIB_DIR) \ -lplc4 \ -lplds4 \ -lnspr4 \ - -lc -#endif + $(NULL) + +endif endif diff --git a/security/nss/lib/freebl/desblapi.c b/security/nss/lib/freebl/desblapi.c index ff038c573..b9b3288ac 100644 --- a/security/nss/lib/freebl/desblapi.c +++ b/security/nss/lib/freebl/desblapi.c @@ -179,12 +179,21 @@ DES_EDE3CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len) } DESContext * -DES_CreateContext(const BYTE * key, const BYTE *iv, int mode, PRBool encrypt) +DES_AllocateContext(void) +{ + return PORT_ZNew(DESContext); +} + +SECStatus +DES_InitContext(DESContext *cx, const unsigned char *key, unsigned int keylen, + const unsigned char *iv, int mode, unsigned int encrypt, + unsigned int unused) { - DESContext *cx = PORT_ZNew(DESContext); DESDirection opposite; - if (!cx) - return 0; + if (!cx) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } cx->direction = encrypt ? DES_ENCRYPT : DES_DECRYPT; opposite = encrypt ? DES_DECRYPT : DES_ENCRYPT; switch (mode) { @@ -228,10 +237,21 @@ DES_CreateContext(const BYTE * key, const BYTE *iv, int mode, PRBool encrypt) break; default: - PORT_Free(cx); - cx = 0; PORT_SetError(SEC_ERROR_INVALID_ARGS); - break; + return SECFailure; + } + return SECSuccess; +} + +DESContext * +DES_CreateContext(const BYTE * key, const BYTE *iv, int mode, PRBool encrypt) +{ + DESContext *cx = PORT_ZNew(DESContext); + SECStatus rv = DES_InitContext(cx, key, 0, iv, mode, encrypt, 0); + + if (rv != SECSuccess) { + PORT_ZFree(cx, sizeof *cx); + cx = NULL; } return cx; } diff --git a/security/nss/lib/freebl/dsa.c b/security/nss/lib/freebl/dsa.c index 85ceb2e51..7f4c42863 100644 --- a/security/nss/lib/freebl/dsa.c +++ b/security/nss/lib/freebl/dsa.c @@ -46,37 +46,24 @@ #include "secitem.h" #include "blapi.h" #include "mpi.h" +#include "secmpi.h" /* XXX to be replaced by define in blapit.h */ #define NSS_FREEBL_DSA_DEFAULT_CHUNKSIZE 2048 -#define CHECKOK(func) if (MP_OKAY > (err = func)) goto cleanup - -#define SECITEM_TO_MPINT(it, mp) \ - CHECKOK(mp_read_unsigned_octets((mp), (it).data, (it).len)) - -/* DSA-specific random number functions defined in prng_fips1861.c. */ -extern SECStatus -DSA_RandomUpdate(void *data, size_t bytes, unsigned char *q); - +/* DSA-specific random number function defined in prng_fips1861.c. */ extern SECStatus -DSA_GenerateGlobalRandomBytes(void *dest, size_t len, unsigned char *q); +DSA_GenerateGlobalRandomBytes(void *dest, size_t len, const unsigned char *q); static void translate_mpi_error(mp_err err) { - switch (err) { - case MP_MEM: PORT_SetError(SEC_ERROR_NO_MEMORY); break; - case MP_RANGE: PORT_SetError(SEC_ERROR_BAD_DATA); break; - case MP_BADARG: PORT_SetError(SEC_ERROR_INVALID_ARGS); break; - default: PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); break; - } + MP_TO_SEC_ERROR(err); } SECStatus dsa_NewKey(const PQGParams *params, DSAPrivateKey **privKey, const unsigned char *xb) { - unsigned int y_len; mp_int p, g; mp_int x, y; mp_err err; @@ -105,29 +92,27 @@ dsa_NewKey(const PQGParams *params, DSAPrivateKey **privKey, MP_DIGITS(&g) = 0; MP_DIGITS(&x) = 0; MP_DIGITS(&y) = 0; - CHECKOK( mp_init(&p) ); - CHECKOK( mp_init(&g) ); - CHECKOK( mp_init(&x) ); - CHECKOK( mp_init(&y) ); + CHECK_MPI_OK( mp_init(&p) ); + CHECK_MPI_OK( mp_init(&g) ); + CHECK_MPI_OK( mp_init(&x) ); + CHECK_MPI_OK( mp_init(&y) ); /* Copy over the PQG params */ - CHECKOK( SECITEM_CopyItem(arena, &key->params.prime, ¶ms->prime) ); - CHECKOK( SECITEM_CopyItem(arena, &key->params.subPrime, ¶ms->subPrime)); - CHECKOK( SECITEM_CopyItem(arena, &key->params.base, ¶ms->base) ); + CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.prime, + ¶ms->prime) ); + CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.subPrime, + ¶ms->subPrime) ); + CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.base, ¶ms->base) ); /* Convert stored p, g, and received x into MPI integers. */ SECITEM_TO_MPINT(params->prime, &p); SECITEM_TO_MPINT(params->base, &g); - CHECKOK( mp_read_unsigned_octets(&x, xb, DSA_SUBPRIME_LEN) ); + OCTETS_TO_MPINT(xb, &x, DSA_SUBPRIME_LEN); /* Store x in private key */ SECITEM_AllocItem(arena, &key->privateValue, DSA_SUBPRIME_LEN); memcpy(key->privateValue.data, xb, DSA_SUBPRIME_LEN); /* Compute public key y = g**x mod p */ - CHECKOK( mp_exptmod(&g, &x, &p, &y) ); + CHECK_MPI_OK( mp_exptmod(&g, &x, &p, &y) ); /* Store y in public key */ - y_len = mp_unsigned_octet_size(&y); - SECITEM_AllocItem(arena, &key->publicValue, y_len); - err = mp_to_unsigned_octets(&y, key->publicValue.data, y_len); - /* mp_to_unsigned_octets returns bytes written (y_len) if okay */ - if (err < 0) goto cleanup; else err = MP_OKAY; + MPINT_TO_SECITEM(&y, &key->publicValue, arena); *privKey = key; key = NULL; cleanup: @@ -155,10 +140,33 @@ DSA_NewKey(const PQGParams *params, DSAPrivateKey **privKey) { SECStatus rv; unsigned char seed[DSA_SUBPRIME_LEN]; - /* Generate seed bytes for x according to FIPS 186-1 appendix 3 */ - if (DSA_GenerateGlobalRandomBytes(seed, DSA_SUBPRIME_LEN, - params->subPrime.data)) + int retries = 10; + int i; + PRBool good; + + do { + /* Generate seed bytes for x according to FIPS 186-1 appendix 3 */ + if (DSA_GenerateGlobalRandomBytes(seed, DSA_SUBPRIME_LEN, + params->subPrime.data)) + return SECFailure; + /* Disallow values of 0 and 1 for x. */ + good = PR_FALSE; + for (i = 0; i < DSA_SUBPRIME_LEN-1; i++) { + if (seed[i] != 0) { + good = PR_TRUE; + break; + } + } + if (!good && seed[i] > 1) { + good = PR_TRUE; + } + } while (!good && --retries > 0); + + if (!good) { + PORT_SetError(SEC_ERROR_NEED_RANDOM); return SECFailure; + } + /* Generate a new DSA key using random seed. */ rv = dsa_NewKey(params, privKey, seed); return rv; @@ -202,13 +210,13 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest, MP_DIGITS(&k) = 0; MP_DIGITS(&r) = 0; MP_DIGITS(&s) = 0; - CHECKOK( mp_init(&p) ); - CHECKOK( mp_init(&q) ); - CHECKOK( mp_init(&g) ); - CHECKOK( mp_init(&x) ); - CHECKOK( mp_init(&k) ); - CHECKOK( mp_init(&r) ); - CHECKOK( mp_init(&s) ); + CHECK_MPI_OK( mp_init(&p) ); + CHECK_MPI_OK( mp_init(&q) ); + CHECK_MPI_OK( mp_init(&g) ); + CHECK_MPI_OK( mp_init(&x) ); + CHECK_MPI_OK( mp_init(&k) ); + CHECK_MPI_OK( mp_init(&r) ); + CHECK_MPI_OK( mp_init(&s) ); /* ** Convert stored PQG and private key into MPI integers. */ @@ -216,24 +224,24 @@ dsa_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest, SECITEM_TO_MPINT(key->params.subPrime, &q); SECITEM_TO_MPINT(key->params.base, &g); SECITEM_TO_MPINT(key->privateValue, &x); - CHECKOK( mp_read_unsigned_octets(&k, kb, DSA_SUBPRIME_LEN) ); + OCTETS_TO_MPINT(kb, &k, DSA_SUBPRIME_LEN); /* ** FIPS 186-1, Section 5, Step 1 ** ** r = (g**k mod p) mod q */ - CHECKOK( mp_exptmod(&g, &k, &p, &r) ); /* r = g**k mod p */ - CHECKOK( mp_mod(&r, &q, &r) ); /* r = r mod q */ + CHECK_MPI_OK( mp_exptmod(&g, &k, &p, &r) ); /* r = g**k mod p */ + CHECK_MPI_OK( mp_mod(&r, &q, &r) ); /* r = r mod q */ /* ** FIPS 186-1, Section 5, Step 2 ** ** s = (k**-1 * (SHA1(M) + x*r)) mod q */ SECITEM_TO_MPINT(*digest, &s); /* s = SHA1(M) */ - CHECKOK( mp_invmod(&k, &q, &k) ); /* k = k**-1 mod q */ - CHECKOK( mp_mulmod(&x, &r, &q, &x) ); /* x = x * r mod q */ - CHECKOK( mp_addmod(&s, &x, &q, &s) ); /* s = s + x mod q */ - CHECKOK( mp_mulmod(&s, &k, &q, &s) ); /* s = s * k mod q */ + CHECK_MPI_OK( mp_invmod(&k, &q, &k) ); /* k = k**-1 mod q */ + CHECK_MPI_OK( mp_mulmod(&x, &r, &q, &x) ); /* x = x * r mod q */ + CHECK_MPI_OK( mp_addmod(&s, &x, &q, &s) ); /* s = s + x mod q */ + CHECK_MPI_OK( mp_mulmod(&s, &k, &q, &s) ); /* s = s * k mod q */ /* ** verify r != 0 and s != 0 ** mentioned as optional in FIPS 186-1. @@ -270,7 +278,7 @@ cleanup: return rv; } -/* signature is caller-supplied buffer of at least 20 bytes. +/* signature is caller-supplied buffer of at least 40 bytes. ** On input, signature->len == size of buffer to hold signature. ** digest->len == size of digest. ** On output, signature->len == size of signature in buffer. @@ -282,6 +290,8 @@ DSA_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest) SECStatus rv; int retries = 10; unsigned char kSeed[DSA_SUBPRIME_LEN]; + int i; + PRBool good; PORT_SetError(0); do { @@ -289,6 +299,19 @@ DSA_SignDigest(DSAPrivateKey *key, SECItem *signature, const SECItem *digest) key->params.subPrime.data); if (rv != SECSuccess) break; + /* Disallow a value of 0 for k. */ + good = PR_FALSE; + for (i = 0; i < DSA_SUBPRIME_LEN; i++) { + if (kSeed[i] != 0) { + good = PR_TRUE; + break; + } + } + if (!good) { + PORT_SetError(SEC_ERROR_NEED_RANDOM); + rv = SECFailure; + continue; + } rv = dsa_SignDigest(key, signature, digest, kSeed); } while (rv != SECSuccess && PORT_GetError() == SEC_ERROR_NEED_RANDOM && --retries > 0); @@ -341,16 +364,16 @@ DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature, MP_DIGITS(&u2) = 0; MP_DIGITS(&v) = 0; MP_DIGITS(&w) = 0; - CHECKOK( mp_init(&p) ); - CHECKOK( mp_init(&q) ); - CHECKOK( mp_init(&g) ); - CHECKOK( mp_init(&y) ); - CHECKOK( mp_init(&r_) ); - CHECKOK( mp_init(&s_) ); - CHECKOK( mp_init(&u1) ); - CHECKOK( mp_init(&u2) ); - CHECKOK( mp_init(&v) ); - CHECKOK( mp_init(&w) ); + CHECK_MPI_OK( mp_init(&p) ); + CHECK_MPI_OK( mp_init(&q) ); + CHECK_MPI_OK( mp_init(&g) ); + CHECK_MPI_OK( mp_init(&y) ); + CHECK_MPI_OK( mp_init(&r_) ); + CHECK_MPI_OK( mp_init(&s_) ); + CHECK_MPI_OK( mp_init(&u1) ); + CHECK_MPI_OK( mp_init(&u2) ); + CHECK_MPI_OK( mp_init(&v) ); + CHECK_MPI_OK( mp_init(&w) ); /* ** Convert stored PQG and public key into MPI integers. */ @@ -361,43 +384,45 @@ DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature, /* ** Convert received signature (r', s') into MPI integers. */ - CHECKOK( mp_read_unsigned_octets(&r_, signature->data, DSA_SUBPRIME_LEN) ); - CHECKOK( mp_read_unsigned_octets(&s_, signature->data + DSA_SUBPRIME_LEN, - DSA_SUBPRIME_LEN) ); + OCTETS_TO_MPINT(signature->data, &r_, DSA_SUBPRIME_LEN); + OCTETS_TO_MPINT(signature->data + DSA_SUBPRIME_LEN, &s_, DSA_SUBPRIME_LEN); /* ** Verify that 0 < r' < q and 0 < s' < q */ if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 || - mp_cmp(&r_, &q) >= 0 || mp_cmp(&s_, &q) >= 0) + mp_cmp(&r_, &q) >= 0 || mp_cmp(&s_, &q) >= 0) { + /* err is zero here. */ + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); goto cleanup; /* will return verified == SECFailure */ + } /* ** FIPS 186-1, Section 6, Step 1 ** ** w = (s')**-1 mod q */ - CHECKOK( mp_invmod(&s_, &q, &w) ); /* w = (s')**-1 mod q */ + CHECK_MPI_OK( mp_invmod(&s_, &q, &w) ); /* w = (s')**-1 mod q */ /* ** FIPS 186-1, Section 6, Step 2 ** ** u1 = ((SHA1(M')) * w) mod q */ - SECITEM_TO_MPINT(*digest, &u1); /* u1 = SHA1(M') */ - CHECKOK( mp_mulmod(&u1, &w, &q, &u1) ); /* u1 = u1 * w mod q */ + SECITEM_TO_MPINT(*digest, &u1); /* u1 = SHA1(M') */ + CHECK_MPI_OK( mp_mulmod(&u1, &w, &q, &u1) ); /* u1 = u1 * w mod q */ /* ** FIPS 186-1, Section 6, Step 3 ** ** u2 = ((r') * w) mod q */ - CHECKOK( mp_mulmod(&r_, &w, &q, &u2) ); + CHECK_MPI_OK( mp_mulmod(&r_, &w, &q, &u2) ); /* ** FIPS 186-1, Section 6, Step 4 ** ** v = ((g**u1 * y**u2) mod p) mod q */ - CHECKOK( mp_exptmod(&g, &u1, &p, &g) ); /* g = g**u1 mod p */ - CHECKOK( mp_exptmod(&y, &u2, &p, &y) ); /* y = y**u2 mod p */ - CHECKOK( mp_mulmod(&g, &y, &p, &v) ); /* v = g * y mod p */ - CHECKOK( mp_mod(&v, &q, &v) ); /* v = v mod q */ + CHECK_MPI_OK( mp_exptmod(&g, &u1, &p, &g) ); /* g = g**u1 mod p */ + CHECK_MPI_OK( mp_exptmod(&y, &u2, &p, &y) ); /* y = y**u2 mod p */ + CHECK_MPI_OK( mp_mulmod(&g, &y, &p, &v) ); /* v = g * y mod p */ + CHECK_MPI_OK( mp_mod(&v, &q, &v) ); /* v = v mod q */ /* ** Verification: v == r' */ diff --git a/security/nss/lib/freebl/ec.c b/security/nss/lib/freebl/ec.c index 1eefdf1f0..53949ab94 100644 --- a/security/nss/lib/freebl/ec.c +++ b/security/nss/lib/freebl/ec.c @@ -115,7 +115,7 @@ ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2, len = (params->fieldID.size + 7) >> 3; if (pointP != NULL) { if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) || - (pointP->len != (2 * len + 1))) { + (pointP->len != (2 * len + 1))) { return SECFailure; }; } @@ -220,21 +220,15 @@ cleanup: return rv; } - -static unsigned char bitmask[] = { - 0xff, 0x7f, 0x3f, 0x1f, - 0x0f, 0x07, 0x03, 0x01 -}; #endif /* NSS_ENABLE_ECC */ /* Generates a new EC key pair. The private key is a supplied - * random value (in seed) and the public key is the result of - * performing a scalar point multiplication of that value with - * the curve's base point. + * value and the public key is the result of performing a scalar + * point multiplication of that value with the curve's base point. */ SECStatus -EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey, - const unsigned char *seed, int seedlen) +ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey, + const unsigned char *privKeyBytes, int privKeyLen) { SECStatus rv = SECFailure; #ifdef NSS_ENABLE_ECC @@ -245,10 +239,10 @@ EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey, int len; #if EC_DEBUG - printf("EC_NewKeyFromSeed called\n"); + printf("ec_NewKey called\n"); #endif - if (!ecParams || !privKey || !seed || (seedlen < 0)) { + if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0)) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } @@ -301,16 +295,17 @@ EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey, CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID, &ecParams->curveOID)); - len = (ecParams->fieldID.size + 7) >> 3; - SECITEM_AllocItem(arena, &key->privateValue, len); + len = (ecParams->fieldID.size + 7) >> 3; SECITEM_AllocItem(arena, &key->publicValue, 2*len + 1); + len = ecParams->order.len; + SECITEM_AllocItem(arena, &key->privateValue, len); /* Copy private key */ - if (seedlen >= len) { - memcpy(key->privateValue.data, seed, len); + if (privKeyLen >= len) { + memcpy(key->privateValue.data, privKeyBytes, len); } else { - memset(key->privateValue.data, 0, (len - seedlen)); - memcpy(key->privateValue.data + (len - seedlen), seed, seedlen); + memset(key->privateValue.data, 0, (len - privKeyLen)); + memcpy(key->privateValue.data + (len - privKeyLen), privKeyBytes, privKeyLen); } /* Compute corresponding public key */ @@ -329,7 +324,7 @@ cleanup: PORT_FreeArena(arena, PR_TRUE); #if EC_DEBUG - printf("EC_NewKeyFromSeed returning %s\n", + printf("ec_NewKey returning %s\n", (rv == SECSuccess) ? "success" : "failure"); #endif #else @@ -340,35 +335,82 @@ cleanup: } +/* Generates a new EC key pair. The private key is a supplied + * random value (in seed) and the public key is the result of + * performing a scalar point multiplication of that value with + * the curve's base point. + */ +SECStatus +EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey, + const unsigned char *seed, int seedlen) +{ + SECStatus rv = SECFailure; +#ifdef NSS_ENABLE_ECC + rv = ec_NewKey(ecParams, privKey, seed, seedlen); +#else + PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); +#endif /* NSS_ENABLE_ECC */ + return rv; +} + /* Generates a new EC key pair. The private key is a random value and * the public key is the result of performing a scalar point multiplication - * of that value with the curve's base point. + * of that value with the curve's base point. The random value for the + * private key is generated using the algorithm A.4.1 of ANSI X9.62, + * modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the + * random number generator. */ SECStatus EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey) { SECStatus rv = SECFailure; #ifdef NSS_ENABLE_ECC + mp_err err; int len; - unsigned char *seed; + unsigned char *privKeyBytes = NULL; + mp_int privKeyVal, order_1, one; if (!ecParams || !privKey) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } - /* Generate random private key */ - len = (ecParams->fieldID.size + 7) >> 3; - if ((seed = PORT_Alloc(len)) == NULL) goto cleanup; - if (RNG_GenerateGlobalRandomBytes(seed, len) != SECSuccess) goto cleanup; - - /* Fit private key to the field size */ - seed[0] &= bitmask[len * 8 - ecParams->fieldID.size]; - rv = EC_NewKeyFromSeed(ecParams, privKey, seed, len); + MP_DIGITS(&privKeyVal) = 0; + MP_DIGITS(&order_1) = 0; + MP_DIGITS(&one) = 0; + CHECK_MPI_OK( mp_init(&privKeyVal) ); + CHECK_MPI_OK( mp_init(&order_1) ); + CHECK_MPI_OK( mp_init(&one) ); + + /* Generate random private key. + * Generates 2*len random bytes using the global random bit generator + * (which implements Algorithm 1 of FIPS 186-2 Change Notice 1) then + * reduces modulo the group order. + */ + len = ecParams->order.len; + if ((privKeyBytes = PORT_Alloc(2*len)) == NULL) goto cleanup; + CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(privKeyBytes, 2*len) ); + CHECK_MPI_OK( mp_read_unsigned_octets(&privKeyVal, privKeyBytes, 2*len) ); + CHECK_MPI_OK( mp_read_unsigned_octets(&order_1, + ecParams->order.data, len) ); + CHECK_MPI_OK( mp_set_int(&one, 1) ); + CHECK_MPI_OK( mp_sub(&order_1, &one, &order_1) ); + CHECK_MPI_OK( mp_mod(&privKeyVal, &order_1, &privKeyVal) ); + CHECK_MPI_OK( mp_add(&privKeyVal, &one, &privKeyVal) ); + CHECK_MPI_OK( mp_to_fixlen_octets(&privKeyVal, privKeyBytes, len) ); + /* generate public key */ + CHECK_SEC_OK( ec_NewKey(ecParams, privKey, privKeyBytes, len) ); cleanup: - if (!seed) { - PORT_ZFree(seed, len); + mp_clear(&privKeyVal); + mp_clear(&order_1); + mp_clear(&one); + if (privKeyBytes) { + PORT_ZFree(privKeyBytes, 2*len); + } + if (err < MP_OKAY) { + MP_TO_SEC_ERROR(err); + rv = SECFailure; } #if EC_DEBUG printf("EC_NewKey returning %s\n", @@ -382,7 +424,7 @@ cleanup: } /* Validates an EC public key as described in Section 5.2.2 of - * X9.63. The ECDH primitive when used without the cofactor does + * X9.62. The ECDH primitive when used without the cofactor does * not address small subgroup attacks, which may occur when the * public key is not valid. These attacks can be prevented by * validating the public key before using ECDH. @@ -391,13 +433,78 @@ SECStatus EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue) { #ifdef NSS_ENABLE_ECC + mp_int Px, Py; + ECGroup *group = NULL; + SECStatus rv = SECFailure; + mp_err err = MP_OKAY; + int len; + if (!ecParams || !publicValue) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } + + /* NOTE: We only support uncompressed points for now */ + len = (ecParams->fieldID.size + 7) >> 3; + if (publicValue->data[0] != EC_POINT_FORM_UNCOMPRESSED) { + PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM); + return SECFailure; + } else if (publicValue->len != (2 * len + 1)) { + PORT_SetError(SEC_ERROR_BAD_KEY); + return SECFailure; + } + + MP_DIGITS(&Px) = 0; + MP_DIGITS(&Py) = 0; + CHECK_MPI_OK( mp_init(&Px) ); + CHECK_MPI_OK( mp_init(&Py) ); + + /* Initialize Px and Py */ + CHECK_MPI_OK( mp_read_unsigned_octets(&Px, publicValue->data + 1, (mp_size) len) ); + CHECK_MPI_OK( mp_read_unsigned_octets(&Py, publicValue->data + 1 + len, (mp_size) len) ); + + /* construct from named params */ + group = ECGroup_fromName(ecParams->name); + if (group == NULL) { + /* + * ECGroup_fromName fails if ecParams->name is not a valid + * ECCurveName value, or if we run out of memory, or perhaps + * for other reasons. Unfortunately if ecParams->name is a + * valid ECCurveName value, we don't know what the right error + * code should be because ECGroup_fromName doesn't return an + * error code to the caller. Set err to MP_UNDEF because + * that's what ECGroup_fromName uses internally. + */ + if ((ecParams->name <= ECCurve_noName) || + (ecParams->name >= ECCurve_pastLastCurve)) { + err = MP_BADARG; + } else { + err = MP_UNDEF; + } + goto cleanup; + } - /* XXX Add actual checks here. */ - return SECSuccess; + /* validate public point */ + if ((err = ECPoint_validate(group, &Px, &Py)) < MP_YES) { + if (err == MP_NO) { + PORT_SetError(SEC_ERROR_BAD_KEY); + rv = SECFailure; + err = MP_OKAY; /* don't change the error code */ + } + goto cleanup; + } + + rv = SECSuccess; + +cleanup: + ECGroup_free(group); + mp_clear(&Px); + mp_clear(&Py); + if (err) { + MP_TO_SEC_ERROR(err); + rv = SECFailure; + } + return rv; #else PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); return SECFailure; diff --git a/security/nss/lib/freebl/ecl/ec2.h b/security/nss/lib/freebl/ecl/ec2.h index a4bf649b9..2ca8418b3 100644 --- a/security/nss/lib/freebl/ecl/ec2.h +++ b/security/nss/lib/freebl/ecl/ec2.h @@ -62,6 +62,9 @@ mp_err ec_GF2m_pt_sub_aff(const mp_int *px, const mp_int *py, mp_err ec_GF2m_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry, const ECGroup *group); +/* Validates a point on a GF2m curve. */ +mp_err ec_GF2m_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group); + /* by default, this routine is unused and thus doesn't need to be compiled */ #ifdef ECL_ENABLE_GF2M_PT_MUL_AFF /* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters diff --git a/security/nss/lib/freebl/ecl/ec2_aff.c b/security/nss/lib/freebl/ecl/ec2_aff.c index eef3f4821..45b277001 100644 --- a/security/nss/lib/freebl/ecl/ec2_aff.c +++ b/security/nss/lib/freebl/ecl/ec2_aff.c @@ -269,3 +269,79 @@ ec_GF2m_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py, return res; } #endif + +/* Validates a point on a GF2m curve. */ +mp_err +ec_GF2m_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group) +{ + mp_err res = MP_NO; + mp_int accl, accr, tmp, pxt, pyt; + + MP_DIGITS(&accl) = 0; + MP_DIGITS(&accr) = 0; + MP_DIGITS(&tmp) = 0; + MP_DIGITS(&pxt) = 0; + MP_DIGITS(&pyt) = 0; + MP_CHECKOK(mp_init(&accl)); + MP_CHECKOK(mp_init(&accr)); + MP_CHECKOK(mp_init(&tmp)); + MP_CHECKOK(mp_init(&pxt)); + MP_CHECKOK(mp_init(&pyt)); + + /* 1: Verify that publicValue is not the point at infinity */ + if (ec_GF2m_pt_is_inf_aff(px, py) == MP_YES) { + res = MP_NO; + goto CLEANUP; + } + /* 2: Verify that the coordinates of publicValue are elements + * of the field. + */ + if ((MP_SIGN(px) == MP_NEG) || (mp_cmp(px, &group->meth->irr) >= 0) || + (MP_SIGN(py) == MP_NEG) || (mp_cmp(py, &group->meth->irr) >= 0)) { + res = MP_NO; + goto CLEANUP; + } + /* 3: Verify that publicValue is on the curve. */ + if (group->meth->field_enc) { + group->meth->field_enc(px, &pxt, group->meth); + group->meth->field_enc(py, &pyt, group->meth); + } else { + mp_copy(px, &pxt); + mp_copy(py, &pyt); + } + /* left-hand side: y^2 + x*y */ + MP_CHECKOK( group->meth->field_sqr(&pyt, &accl, group->meth) ); + MP_CHECKOK( group->meth->field_mul(&pxt, &pyt, &tmp, group->meth) ); + MP_CHECKOK( group->meth->field_mul(&pxt, &pyt, &tmp, group->meth) ); + MP_CHECKOK( group->meth->field_add(&accl, &tmp, &accl, group->meth) ); + /* right-hand side: x^3 + a*x^2 + b */ + MP_CHECKOK( group->meth->field_sqr(&pxt, &tmp, group->meth) ); + MP_CHECKOK( group->meth->field_mul(&pxt, &tmp, &accr, group->meth) ); + MP_CHECKOK( group->meth->field_mul(&group->curvea, &tmp, &tmp, group->meth) ); + MP_CHECKOK( group->meth->field_add(&tmp, &accr, &accr, group->meth) ); + MP_CHECKOK( group->meth->field_add(&accr, &group->curveb, &accr, group->meth) ); + /* check LHS - RHS == 0 */ + MP_CHECKOK( group->meth->field_add(&accl, &accr, &accr, group->meth) ); + if (mp_cmp_z(&accr) != 0) { + res = MP_NO; + goto CLEANUP; + } + /* 4: Verify that the order of the curve times the publicValue + * is the point at infinity. + */ + MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt) ); + if (ec_GF2m_pt_is_inf_aff(&pxt, &pyt) != MP_YES) { + res = MP_NO; + goto CLEANUP; + } + + res = MP_YES; + +CLEANUP: + mp_clear(&accl); + mp_clear(&accr); + mp_clear(&tmp); + mp_clear(&pxt); + mp_clear(&pyt); + return res; +} diff --git a/security/nss/lib/freebl/ecl/ecl-curve.h b/security/nss/lib/freebl/ecl/ecl-curve.h index cba22b2a7..fed21fa52 100644 --- a/security/nss/lib/freebl/ecl/ecl-curve.h +++ b/security/nss/lib/freebl/ecl/ecl-curve.h @@ -117,7 +117,7 @@ static const ECCurveParams ecCurve_NIST_K233 = { "000000000000000000000000000000000000000000000000000000000001", "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126", "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3", - "008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", 4 + "8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", 4 }; static const ECCurveParams ecCurve_NIST_B233 = { "NIST-B233", ECField_GF2m, 233, @@ -155,7 +155,7 @@ static const ECCurveParams ecCurve_NIST_K409 = { "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746", "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B", - "007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF", + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF", 4 }; static const ECCurveParams ecCurve_NIST_B409 = { diff --git a/security/nss/lib/freebl/ecl/ecl-priv.h b/security/nss/lib/freebl/ecl/ecl-priv.h index 39072e374..bce7ccf09 100644 --- a/security/nss/lib/freebl/ecl/ecl-priv.h +++ b/security/nss/lib/freebl/ecl/ecl-priv.h @@ -144,6 +144,7 @@ struct ECGroupStr { mp_err (*points_mul) (const mp_int *k1, const mp_int *k2, const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry, const ECGroup *group); + mp_err (*validate_point) (const mp_int *px, const mp_int *py, const ECGroup *group); /* Extra storage for implementation-specific data. Any memory * allocated to these extra fields will be cleared by extra_free. */ void *extra1; diff --git a/security/nss/lib/freebl/ecl/ecl.c b/security/nss/lib/freebl/ecl/ecl.c index 5dc853647..520755f6a 100644 --- a/security/nss/lib/freebl/ecl/ecl.c +++ b/security/nss/lib/freebl/ecl/ecl.c @@ -68,6 +68,7 @@ ECGroup_new() MP_CHECKOK(mp_init(&group->order)); group->base_point_mul = NULL; group->points_mul = NULL; + group->validate_point = NULL; group->extra1 = NULL; group->extra2 = NULL; group->extra_free = NULL; @@ -110,6 +111,7 @@ ECGroup_consGFp(const mp_int *irr, const mp_int *curvea, group->point_mul = &ec_GFp_pt_mul_jm_wNAF; group->base_point_mul = NULL; group->points_mul = &ec_GFp_pts_mul_jac; + group->validate_point = &ec_GFp_validate_point; CLEANUP: if (res != MP_OKAY) { @@ -152,6 +154,7 @@ ECGroup_consGFp_mont(const mp_int *irr, const mp_int *curvea, group->point_mul = &ec_GFp_pt_mul_jm_wNAF; group->base_point_mul = NULL; group->points_mul = &ec_GFp_pts_mul_jac; + group->validate_point = &ec_GFp_validate_point; CLEANUP: if (res != MP_OKAY) { @@ -193,6 +196,7 @@ ECGroup_consGF2m(const mp_int *irr, const unsigned int irr_arr[5], group->point_mul = &ec_GF2m_pt_mul_mont; group->base_point_mul = NULL; group->points_mul = &ec_pts_mul_basic; + group->validate_point = &ec_GF2m_validate_point; CLEANUP: if (res != MP_OKAY) { @@ -329,11 +333,10 @@ ecgroup_fromNameAndHex(const ECCurveName name, /* set name, if any */ if (params->text != NULL) { - group->text = (char *) malloc(sizeof(char) * strlen(params->text)); + group->text = strdup(params->text); if (group->text == NULL) { res = MP_MEM; } - strcpy(group->text, params->text); } CLEANUP: @@ -391,6 +394,21 @@ ECGroup_fromName(const ECCurveName name) return group; } +/* Validates an EC public key as described in Section 5.2.2 of X9.62. */ +mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const + mp_int *py) +{ + /* 1: Verify that publicValue is not the point at infinity */ + /* 2: Verify that the coordinates of publicValue are elements + * of the field. + */ + /* 3: Verify that publicValue is on the curve. */ + /* 4: Verify that the order of the curve times the publicValue + * is the point at infinity. + */ + return group->validate_point(px, py, group); +} + /* Free the memory allocated (if any) to an ECGroup object. */ void ECGroup_free(ECGroup *group) diff --git a/security/nss/lib/freebl/ecl/ecl.h b/security/nss/lib/freebl/ecl/ecl.h index 6d8fb5a59..dbd86c253 100644 --- a/security/nss/lib/freebl/ecl/ecl.h +++ b/security/nss/lib/freebl/ecl/ecl.h @@ -81,4 +81,11 @@ mp_err ECPoints_mul(const ECGroup *group, const mp_int *k1, const mp_int *k2, const mp_int *px, const mp_int *py, mp_int *qx, mp_int *qy); +/* Validates an EC public key as described in Section 5.2.2 of X9.62. + * Returns MP_YES if the public key is valid, MP_NO if the public key + * is invalid, or an error code if the validation could not be + * performed. */ +mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const + mp_int *py); + #endif /* __ecl_h_ */ diff --git a/security/nss/lib/freebl/ecl/ecl_mult.c b/security/nss/lib/freebl/ecl/ecl_mult.c index ede2b0e02..106c7ee42 100644 --- a/security/nss/lib/freebl/ecl/ecl_mult.c +++ b/security/nss/lib/freebl/ecl/ecl_mult.c @@ -41,7 +41,6 @@ #include "ecl.h" #include "ecl-priv.h" #include <stdlib.h> -#include <strings.h> /* Elliptic curve scalar-point multiplication. Computes R(x, y) = k * P(x, * y). If x, y = NULL, then P is assumed to be the generator (base point) @@ -163,7 +162,6 @@ ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2, const mp_int *px, { mp_err res = MP_OKAY; mp_int precomp[4][4][2]; - mp_digit precomp_arr[ECL_MAX_FIELD_SIZE_DIGITS * 4 * 4 * 2], *t; const mp_int *a, *b; int i, j; int ai, bi, d; @@ -181,23 +179,18 @@ ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2, const mp_int *px, } /* initialize precomputation table */ - t = precomp_arr; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { - /* x co-ord */ - MP_SIGN(&precomp[i][j][0]) = MP_ZPOS; - MP_ALLOC(&precomp[i][j][0]) = ECL_MAX_FIELD_SIZE_DIGITS; - MP_USED(&precomp[i][j][0]) = 1; - *t = 0; - MP_DIGITS(&precomp[i][j][0]) = t; - t += ECL_MAX_FIELD_SIZE_DIGITS; - /* y co-ord */ - MP_SIGN(&precomp[i][j][1]) = MP_ZPOS; - MP_ALLOC(&precomp[i][j][1]) = ECL_MAX_FIELD_SIZE_DIGITS; - MP_USED(&precomp[i][j][1]) = 1; - *t = 0; - MP_DIGITS(&precomp[i][j][1]) = t; - t += ECL_MAX_FIELD_SIZE_DIGITS; + MP_DIGITS(&precomp[i][j][0]) = 0; + MP_DIGITS(&precomp[i][j][1]) = 0; + } + } + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + MP_CHECKOK( mp_init_size(&precomp[i][j][0], + ECL_MAX_FIELD_SIZE_DIGITS) ); + MP_CHECKOK( mp_init_size(&precomp[i][j][1], + ECL_MAX_FIELD_SIZE_DIGITS) ); } } @@ -299,6 +292,12 @@ ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2, const mp_int *px, } CLEANUP: + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + mp_clear(&precomp[i][j][0]); + mp_clear(&precomp[i][j][1]); + } + } return res; } @@ -345,17 +344,13 @@ ECPoints_mul(const ECGroup *group, const mp_int *k1, const mp_int *k2, /* if points_mul is defined, then use it */ if (group->points_mul) { - return group->points_mul(k1p, k2p, px, py, rx, ry, group); + res = group->points_mul(k1p, k2p, px, py, rx, ry, group); } else { - return ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group); + res = ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group); } CLEANUP: - if (k1 != k1p) { - mp_clear(&k1t); - } - if (k2 != k2p) { - mp_clear(&k2t); - } + mp_clear(&k1t); + mp_clear(&k2t); return res; } diff --git a/security/nss/lib/freebl/ecl/ecp.h b/security/nss/lib/freebl/ecl/ecp.h index 43c6dcb5b..1d247b154 100644 --- a/security/nss/lib/freebl/ecl/ecp.h +++ b/security/nss/lib/freebl/ecl/ecp.h @@ -62,6 +62,9 @@ mp_err ec_GFp_pt_sub_aff(const mp_int *px, const mp_int *py, mp_err ec_GFp_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry, const ECGroup *group); +/* Validates a point on a GFp curve. */ +mp_err ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group); + #ifdef ECL_ENABLE_GFP_PT_MUL_AFF /* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters * a, b and p are the elliptic curve coefficients and the prime that diff --git a/security/nss/lib/freebl/ecl/ecp_aff.c b/security/nss/lib/freebl/ecl/ecp_aff.c index 1831e4bea..cda04ed22 100644 --- a/security/nss/lib/freebl/ecl/ecp_aff.c +++ b/security/nss/lib/freebl/ecl/ecp_aff.c @@ -282,3 +282,76 @@ ec_GFp_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py, return res; } #endif + +/* Validates a point on a GFp curve. */ +mp_err +ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group) +{ + mp_err res = MP_NO; + mp_int accl, accr, tmp, pxt, pyt; + + MP_DIGITS(&accl) = 0; + MP_DIGITS(&accr) = 0; + MP_DIGITS(&tmp) = 0; + MP_DIGITS(&pxt) = 0; + MP_DIGITS(&pyt) = 0; + MP_CHECKOK(mp_init(&accl)); + MP_CHECKOK(mp_init(&accr)); + MP_CHECKOK(mp_init(&tmp)); + MP_CHECKOK(mp_init(&pxt)); + MP_CHECKOK(mp_init(&pyt)); + + /* 1: Verify that publicValue is not the point at infinity */ + if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) { + res = MP_NO; + goto CLEANUP; + } + /* 2: Verify that the coordinates of publicValue are elements + * of the field. + */ + if ((MP_SIGN(px) == MP_NEG) || (mp_cmp(px, &group->meth->irr) >= 0) || + (MP_SIGN(py) == MP_NEG) || (mp_cmp(py, &group->meth->irr) >= 0)) { + res = MP_NO; + goto CLEANUP; + } + /* 3: Verify that publicValue is on the curve. */ + if (group->meth->field_enc) { + group->meth->field_enc(px, &pxt, group->meth); + group->meth->field_enc(py, &pyt, group->meth); + } else { + mp_copy(px, &pxt); + mp_copy(py, &pyt); + } + /* left-hand side: y^2 */ + MP_CHECKOK( group->meth->field_sqr(&pyt, &accl, group->meth) ); + /* right-hand side: x^3 + a*x + b */ + MP_CHECKOK( group->meth->field_sqr(&pxt, &tmp, group->meth) ); + MP_CHECKOK( group->meth->field_mul(&pxt, &tmp, &accr, group->meth) ); + MP_CHECKOK( group->meth->field_mul(&group->curvea, &pxt, &tmp, group->meth) ); + MP_CHECKOK( group->meth->field_add(&tmp, &accr, &accr, group->meth) ); + MP_CHECKOK( group->meth->field_add(&accr, &group->curveb, &accr, group->meth) ); + /* check LHS - RHS == 0 */ + MP_CHECKOK( group->meth->field_sub(&accl, &accr, &accr, group->meth) ); + if (mp_cmp_z(&accr) != 0) { + res = MP_NO; + goto CLEANUP; + } + /* 4: Verify that the order of the curve times the publicValue + * is the point at infinity. + */ + MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt) ); + if (ec_GFp_pt_is_inf_aff(&pxt, &pyt) != MP_YES) { + res = MP_NO; + goto CLEANUP; + } + + res = MP_YES; + +CLEANUP: + mp_clear(&accl); + mp_clear(&accr); + mp_clear(&tmp); + mp_clear(&pxt); + mp_clear(&pyt); + return res; +} diff --git a/security/nss/lib/freebl/ecl/ecp_jm.c b/security/nss/lib/freebl/ecl/ecp_jm.c index 397e01f47..3b19cc825 100644 --- a/security/nss/lib/freebl/ecl/ecp_jm.c +++ b/security/nss/lib/freebl/ecl/ecp_jm.c @@ -283,7 +283,7 @@ ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py, orderBitSize = mpl_significant_bits(&group->order); /* Allocate memory for NAF */ - naf = (signed char *) malloc(sizeof(signed char) * orderBitSize); + naf = (signed char *) malloc(sizeof(signed char) * (orderBitSize + 1)); if (naf == NULL) { res = MP_MEM; goto CLEANUP; diff --git a/security/nss/lib/freebl/ecl/tests/ec2_test.c b/security/nss/lib/freebl/ecl/tests/ec2_test.c index 1c7639d1a..e82b47da0 100644 --- a/security/nss/lib/freebl/ecl/tests/ec2_test.c +++ b/security/nss/lib/freebl/ecl/tests/ec2_test.c @@ -348,6 +348,19 @@ ectest_curve_GF2m(ECGroup *group, int ectestPrint, int ectestTime, goto CLEANUP; } + /* test validate_point function */ + if (ECPoint_validate(group, &gx, &gy) != MP_YES) { + printf(" Error: validate point on base point failed.\n"); + res = MP_NO; + goto CLEANUP; + } + MP_CHECKOK(mp_add_d(&gy, 1, &ry)); + if (ECPoint_validate(group, &gx, &ry) != MP_NO) { + printf(" Error: validate point on invalid point passed.\n"); + res = MP_NO; + goto CLEANUP; + } + if (ectestTime) { /* compute random scalar */ size = mpl_significant_bits(&group->meth->irr); diff --git a/security/nss/lib/freebl/ecl/tests/ecp_test.c b/security/nss/lib/freebl/ecl/tests/ecp_test.c index 9e3ae4d99..d7ce299ec 100644 --- a/security/nss/lib/freebl/ecl/tests/ecp_test.c +++ b/security/nss/lib/freebl/ecl/tests/ecp_test.c @@ -310,6 +310,19 @@ ectest_curve_GFp(ECGroup *group, int ectestPrint, int ectestTime, goto CLEANUP; } + /* test validate_point function */ + if (ECPoint_validate(group, &gx, &gy) != MP_YES) { + printf(" Error: validate point on base point failed.\n"); + res = MP_NO; + goto CLEANUP; + } + MP_CHECKOK(mp_add_d(&gy, 1, &ry)); + if (ECPoint_validate(group, &gx, &ry) != MP_NO) { + printf(" Error: validate point on invalid point passed.\n"); + res = MP_NO; + goto CLEANUP; + } + if (ectestTime) { /* compute random scalar */ size = mpl_significant_bits(&group->meth->irr); diff --git a/security/nss/lib/freebl/freebl.def b/security/nss/lib/freebl/freebl.def new file mode 100644 index 000000000..61b3337c2 --- /dev/null +++ b/security/nss/lib/freebl/freebl.def @@ -0,0 +1,58 @@ +;+# +;+# ***** BEGIN LICENSE BLOCK ***** +;+# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +;+# +;+# The contents of this file are subject to the Mozilla Public License Version +;+# 1.1 (the "License"); you may not use this file except in compliance with +;+# the License. You may obtain a copy of the License at +;+# http://www.mozilla.org/MPL/ +;+# +;+# Software distributed under the License is distributed on an "AS IS" basis, +;+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +;+# for the specific language governing rights and limitations under the +;+# License. +;+# +;+# The Original Code is the Netscape security libraries. +;+# +;+# The Initial Developer of the Original Code is +;+# Netscape Communications Corporation. +;+# Portions created by the Initial Developer are Copyright (C) 2000 +;+# the Initial Developer. All Rights Reserved. +;+# +;+# Contributor(s): +;+# +;+# Alternatively, the contents of this file may be used under the terms of +;+# either the GNU General Public License Version 2 or later (the "GPL"), or +;+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +;+# in which case the provisions of the GPL or the LGPL are applicable instead +;+# of those above. If you wish to allow use of your version of this file only +;+# under the terms of either the GPL or the LGPL, and not to allow others to +;+# use your version of this file under the terms of the MPL, indicate your +;+# decision by deleting the provisions above and replace them with the notice +;+# and other provisions required by the GPL or the LGPL. If you do not delete +;+# the provisions above, a recipient may use your version of this file under +;+# the terms of any one of the MPL, the GPL or the LGPL. +;+# +;+# ***** END LICENSE BLOCK ***** +;+# +;+# OK, this file is meant to support SUN, LINUX, AIX and WINDOWS +;+# 1. For all unix platforms, the string ";-" means "remove this line" +;+# 2. For all unix platforms, the string " DATA " will be removed from any +;+# line on which it occurs. +;+# 3. Lines containing ";+" will have ";+" removed on SUN and LINUX. +;+# On AIX, lines containing ";+" will be removed. +;+# 4. For all unix platforms, the string ";;" will thave the ";;" removed. +;+# 5. For all unix platforms, after the above processing has taken place, +;+# all characters after the first ";" on the line will be removed. +;+# And for AIX, the first ";" will also be removed. +;+# This file is passed directly to windows. Since ';' is a comment, all UNIX +;+# directives are hidden behind ";", ";+", and ";-" +;+ +;+NSSprivate_3.11 { # NSS 3.11 release +;+ global: +LIBRARY freebl3 ;- +EXPORTS ;- +FREEBL_GetVector; +;+ local: +;+ *; +;+}; diff --git a/security/nss/lib/freebl/freeblver.c b/security/nss/lib/freebl/freeblver.c new file mode 100644 index 000000000..e2c6a538c --- /dev/null +++ b/security/nss/lib/freebl/freeblver.c @@ -0,0 +1,56 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* Library identity and versioning */ + +#include "nss.h" + +#if defined(DEBUG) +#define _DEBUG_STRING " (debug)" +#else +#define _DEBUG_STRING "" +#endif + +/* + * Version information for the 'ident' and 'what commands + * + * NOTE: the first component of the concatenated rcsid string + * must not end in a '$' to prevent rcs keyword substitution. + */ +const char __nss_freebl_rcsid[] = "$Header: NSS " NSS_VERSION _DEBUG_STRING + " " __DATE__ " " __TIME__ " $"; +const char __nss_freebl_sccsid[] = "@(#)NSS " NSS_VERSION _DEBUG_STRING + " " __DATE__ " " __TIME__; diff --git a/security/nss/lib/freebl/ldvector.c b/security/nss/lib/freebl/ldvector.c index 63bd76fcb..595d7dd8b 100644 --- a/security/nss/lib/freebl/ldvector.c +++ b/security/nss/lib/freebl/ldvector.c @@ -40,8 +40,10 @@ /* $Id$ */ #include "loader.h" +#include "alghmac.h" -static const struct FREEBLVectorStr vector = { +static const struct FREEBLVectorStr vector = +{ sizeof vector, FREEBL_VERSION, @@ -185,12 +187,52 @@ static const struct FREEBLVectorStr vector = { ECDSA_SignDigestWithSeed, /* End of Version 3.006. */ + /* End of Version 3.007. */ + + AES_InitContext, + AESKeyWrap_InitContext, + DES_InitContext, + RC2_InitContext, + RC4_InitContext, + + AES_AllocateContext, + AESKeyWrap_AllocateContext, + DES_AllocateContext, + RC2_AllocateContext, + RC4_AllocateContext, + + MD2_Clone, + MD5_Clone, + SHA1_Clone, + SHA256_Clone, + SHA384_Clone, + SHA512_Clone, + + TLS_PRF, + HASH_GetRawHashObject, + + HMAC_Create, + HMAC_Init, + HMAC_Begin, + HMAC_Update, + HMAC_Clone, + HMAC_Finish, + HMAC_Destroy, + + RNG_SystemInfoForRNG, + + /* End of Version 3.008. */ }; - const FREEBLVector * FREEBL_GetVector(void) { - return &vector; + extern const char __nss_freebl_rcsid[]; + extern const char __nss_freebl_sccsid[]; + + /* force a reference that won't get optimized away */ + volatile char c = __nss_freebl_rcsid[0] + __nss_freebl_sccsid[0]; + + return &vector; } diff --git a/security/nss/lib/freebl/loader.c b/security/nss/lib/freebl/loader.c index 3b3c4a68a..141cc1b7f 100644 --- a/security/nss/lib/freebl/loader.c +++ b/security/nss/lib/freebl/loader.c @@ -44,190 +44,242 @@ #include "prerror.h" #include "prinit.h" -#if defined(SOLARIS) +static const char* default_name = + SHLIB_PREFIX"freebl"SHLIB_VERSION"."SHLIB_SUFFIX; + +/* getLibName() returns the name of the library to load. */ + +#if defined(SOLARIS) && defined(__sparc) #include <stddef.h> #include <strings.h> #include <sys/systeminfo.h> -#if defined(SOLARIS2_5) -static int -isHybrid(void) -{ - long buflen; - int rv = 0; /* false */ - char buf[256]; - buflen = sysinfo(SI_MACHINE, buf, sizeof buf); - if (buflen > 0) { - rv = (!strcmp(buf, "sun4u") || !strcmp(buf, "sun4u1")); - } - return rv; -} -#else /* SunOS2.6or higher has SI_ISALIST */ -static int -isHybrid(void) + +#if defined(NSS_USE_64) + +const static char fpu_hybrid_shared_lib[] = "libfreebl_64fpu_3.so"; +const static char int_hybrid_shared_lib[] = "libfreebl_64int_3.so"; +const static char non_hybrid_shared_lib[] = "libfreebl_64fpu_3.so"; + +const static char int_hybrid_isa[] = "sparcv9"; +const static char fpu_hybrid_isa[] = "sparcv9+vis"; + +#else + +const static char fpu_hybrid_shared_lib[] = "libfreebl_32fpu_3.so"; +const static char int_hybrid_shared_lib[] = "libfreebl_32int64_3.so"; +const static char non_hybrid_shared_lib[] = "libfreebl_32int_3.so"; + +const static char int_hybrid_isa[] = "sparcv8plus"; +const static char fpu_hybrid_isa[] = "sparcv8plus+vis"; + +#endif + +static const char * +getLibName(void) { + char * found_int_hybrid; + char * found_fpu_hybrid; long buflen; - int rv = 0; /* false */ char buf[256]; + buflen = sysinfo(SI_ISALIST, buf, sizeof buf); - if (buflen > 0) { -#if defined(NSS_USE_64) - char * found = strstr(buf, "sparcv9+vis"); -#else - char * found = strstr(buf, "sparcv8plus+vis"); -#endif - rv = (found != 0); + if (buflen <= 0) + return NULL; + /* The ISA list is a space separated string of names of ISAs and + * ISA extensions, in order of decreasing performance. + * There are two different ISAs with which NSS's crypto code can be + * accelerated. If both are in the list, we take the first one. + * If one is in the list, we use it, and if neither then we use + * the base unaccelerated code. + */ + found_int_hybrid = strstr(buf, int_hybrid_isa); + found_fpu_hybrid = strstr(buf, fpu_hybrid_isa); + if (found_fpu_hybrid && + (!found_int_hybrid || + (found_int_hybrid - found_fpu_hybrid) >= 0)) { + return fpu_hybrid_shared_lib; + } + if (found_int_hybrid) { + return int_hybrid_shared_lib; } - return rv; + return non_hybrid_shared_lib; } -#endif -#elif defined(HPUX) + +#elif defined(HPUX) && !defined(NSS_USE_64) && !defined(__ia64) /* This code tests to see if we're running on a PA2.x CPU. ** It returns true (1) if so, and false (0) otherwise. */ -static int -isHybrid(void) +static const char * +getLibName(void) { long cpu = sysconf(_SC_CPU_VERSION); - return (cpu == CPU_PA_RISC2_0); + return (cpu == CPU_PA_RISC2_0) + ? "libfreebl_32fpu_3.sl" + : "libfreebl_32int32_3.sl" ; } - #else -#error "code for this platform is missing." +/* default case, for platforms/ABIs that have only one freebl shared lib. */ +static const char * getLibName(void) { return default_name; } #endif -/* - * On Solaris, if an application using libnss3.so is linked - * with the -R linker option, the -R search patch is only used - * to search for the direct dependencies of the application - * (such as libnss3.so) and is not used to search for the - * dependencies of libnss3.so. So we build libnss3.so with - * the -R '$ORIGIN' linker option to instruct it to search for - * its dependencies (libfreebl_*.so) in the same directory - * where it resides. This requires that libnss3.so, not - * libnspr4.so, be the shared library that calls dlopen(). - * Therefore we have to duplicate the relevant code in the PR - * load library functions here. - */ - -#if defined(SOLARIS) - -#include <dlfcn.h> +#ifdef XP_UNIX +#include <unistd.h> -typedef struct { - void *dlh; -} BLLibrary; - -static BLLibrary * -bl_LoadLibrary(const char *name) -{ - BLLibrary *lib; - const char *error; - Dl_info dli; +#define BL_MAXSYMLINKS 20 - lib = PR_NEWZAP(BLLibrary); - if (NULL == lib) { - PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); +/* + * If 'link' is a symbolic link, this function follows the symbolic links + * and returns the pathname of the ultimate source of the symbolic links. + * If 'link' is not a symbolic link, this function returns NULL. + * The caller should call PR_Free to free the string returned by this + * function. + */ +static char* bl_GetOriginalPathname(const char* link) +{ + char* resolved = NULL; + char* input = NULL; + PRUint32 iterations = 0; + PRInt32 len = 0, retlen = 0; + if (!link) { + PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return NULL; } - - /* - * In setuid applications, Solaris is unwilling to load freebl unless - * we specify an absolute path. We construct one from the path of the - * library that contains this function. - */ - if (dladdr((void *)bl_LoadLibrary, &dli) != 0) { - const char *slash = strrchr(dli.dli_fname, '/'); - if (slash) { - size_t dirsize = slash - dli.dli_fname + 1; - char *pathname = PR_Malloc(dirsize + strlen(name) + 1); - if (NULL == pathname) { - PR_Free(lib); - PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); - return NULL; - } - memcpy(pathname, dli.dli_fname, dirsize); - strcpy(pathname + dirsize, name); - lib->dlh = dlopen(pathname, RTLD_NOW | RTLD_LOCAL); - PR_Free(pathname); - if (NULL != lib->dlh) - return lib; + len = PR_MAX(1024, strlen(link) + 1); + resolved = PR_Malloc(len); + input = PR_Malloc(len); + if (!resolved || !input) { + if (resolved) { + PR_Free(resolved); + } + if (input) { + PR_Free(input); } - } - - lib->dlh = dlopen(name, RTLD_NOW | RTLD_LOCAL); - if (NULL == lib->dlh) { - PR_SetError(PR_LOAD_LIBRARY_ERROR, 0); - error = dlerror(); - if (NULL != error) - PR_SetErrorText(strlen(error), error); - PR_Free(lib); return NULL; } - return lib; -} - -static void * -bl_FindSymbol(BLLibrary *lib, const char *name) -{ - void *f; - const char *error; - - f = dlsym(lib->dlh, name); - if (NULL == f) { - PR_SetError(PR_FIND_SYMBOL_ERROR, 0); - error = dlerror(); - if (NULL != error) - PR_SetErrorText(strlen(error), error); + strcpy(input, link); + while ( (iterations++ < BL_MAXSYMLINKS) && + ( (retlen = readlink(input, resolved, len - 1)) > 0) ) { + char* tmp = input; + resolved[retlen] = '\0'; /* NULL termination */ + input = resolved; + resolved = tmp; } - return f; -} - -static PRStatus -bl_UnloadLibrary(BLLibrary *lib) -{ - const char *error; - - if (dlclose(lib->dlh) == -1) { - PR_SetError(PR_UNLOAD_LIBRARY_ERROR, 0); - error = dlerror(); - if (NULL != error) - PR_SetErrorText(strlen(error), error); - return PR_FAILURE; + PR_Free(resolved); + if (iterations == 1 && retlen < 0) { + PR_Free(input); + input = NULL; } - PR_Free(lib); - return PR_SUCCESS; + return input; } +#endif /* XP_UNIX */ + +/* + * We use PR_GetLibraryFilePathname to get the pathname of the loaded + * shared lib that contains this function, and then do a PR_LoadLibrary + * with an absolute pathname for the freebl shared library. + */ -#elif defined(HPUX) +#include "prio.h" +#include "prprf.h" +#include <stdio.h> +#include "prsystem.h" -#include <dl.h> -#include <string.h> -#include <errno.h> +const char* softoken=SHLIB_PREFIX"softokn"SOFTOKEN_SHLIB_VERSION"."SHLIB_SUFFIX; typedef struct { - shl_t dlh; + PRLibrary *dlh; } BLLibrary; +/* + * Load the freebl library with the file name 'name' residing in the same + * directory as libsoftoken, whose pathname is 'softokenPath'. + */ +static PRLibrary * +bl_LoadFreeblLibInSoftokenDir(const char *softokenPath, const char *name) +{ + PRLibrary *dlh = NULL; + char *fullName = NULL; + char* c; + PRLibSpec libSpec; + + /* Remove "libsoftokn" from the pathname and add the freebl libname */ + c = strrchr(softokenPath, PR_GetDirectorySeparator()); + if (c) { + size_t softoknPathSize = 1 + c - softokenPath; + fullName = (char*) PORT_Alloc(strlen(name) + softoknPathSize + 1); + if (fullName) { + memcpy(fullName, softokenPath, softoknPathSize); + strcpy(fullName + softoknPathSize, name); +#ifdef DEBUG_LOADER + PR_fprintf(PR_STDOUT, "\nAttempting to load fully-qualified %s\n", + fullName); +#endif + libSpec.type = PR_LibSpec_Pathname; + libSpec.value.pathname = fullName; + dlh = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL); + PORT_Free(fullName); + } + } + return dlh; +} + static BLLibrary * bl_LoadLibrary(const char *name) { - BLLibrary *lib; - const char *error; + BLLibrary *lib = NULL; + PRFuncPtr fn_addr; + char* softokenPath = NULL; + PRLibSpec libSpec; lib = PR_NEWZAP(BLLibrary); if (NULL == lib) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); return NULL; } - lib->dlh = shl_load(name, DYNAMIC_PATH | BIND_IMMEDIATE, 0L); + + /* Get the pathname for the loaded libsoftokn, i.e. /usr/lib/libsoftokn3.so + * PR_GetLibraryFilePathname works with either the base library name or a + * function pointer, depending on the platform. We can't query an exported + * symbol such as NSC_GetFunctionList, because on some platforms we can't + * find symbols in loaded implicit dependencies such as libsoftokn. + * But we can just get the address of this function ! + */ + fn_addr = (PRFuncPtr) &bl_LoadLibrary; + softokenPath = PR_GetLibraryFilePathname(softoken, fn_addr); + + if (softokenPath) { + lib->dlh = bl_LoadFreeblLibInSoftokenDir(softokenPath, name); +#ifdef XP_UNIX + if (!lib->dlh) { + /* + * If softokenPath is a symbolic link, resolve the symbolic + * link and try again. + */ + char* originalSoftokenPath = bl_GetOriginalPathname(softokenPath); + if (originalSoftokenPath) { + PR_Free(softokenPath); + softokenPath = originalSoftokenPath; + lib->dlh = bl_LoadFreeblLibInSoftokenDir(softokenPath, name); + } + } +#endif + PR_Free(softokenPath); + } + if (!lib->dlh) { +#ifdef DEBUG_LOADER + PR_fprintf(PR_STDOUT, "\nAttempting to load %s\n", name); +#endif + libSpec.type = PR_LibSpec_Pathname; + libSpec.value.pathname = name; + lib->dlh = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW | PR_LD_LOCAL); + } if (NULL == lib->dlh) { - PR_SetError(PR_LOAD_LIBRARY_ERROR, errno); - error = strerror(errno); - if (NULL != error) - PR_SetErrorText(strlen(error), error); +#ifdef DEBUG_LOADER + PR_fprintf(PR_STDOUT, "\nLoading failed : %s.\n", name); +#endif PR_Free(lib); - return NULL; + lib = NULL; } return lib; } @@ -236,38 +288,21 @@ static void * bl_FindSymbol(BLLibrary *lib, const char *name) { void *f; - const char *error; - - if (shl_findsym(&lib->dlh, name, TYPE_PROCEDURE, &f) == -1) { - f = NULL; - PR_SetError(PR_FIND_SYMBOL_ERROR, errno); - error = strerror(errno); - if (NULL != error) - PR_SetErrorText(strlen(error), error); - } + + f = PR_FindSymbol(lib->dlh, name); return f; } static PRStatus bl_UnloadLibrary(BLLibrary *lib) { - const char *error; - - if (shl_unload(lib->dlh) == -1) { - PR_SetError(PR_UNLOAD_LIBRARY_ERROR, errno); - error = strerror(errno); - if (NULL != error) - PR_SetErrorText(strlen(error), error); + if (PR_SUCCESS != PR_UnloadLibrary(lib->dlh)) { return PR_FAILURE; } PR_Free(lib); return PR_SUCCESS; } -#else -#error "code for this platform is missing." -#endif - #define LSB(x) ((x)&0xff) #define MSB(x) ((x)>>8) @@ -279,18 +314,13 @@ static const char *libraryName = NULL; static PRStatus freebl_LoadDSO( void ) { - int hybrid = isHybrid(); BLLibrary * handle; - const char * name; + const char * name = getLibName(); - name = hybrid ? -#if defined( AIX ) - "libfreebl_hybrid_3_shr.a" : "libfreebl_pure32_3_shr.a"; -#elif defined( HPUX ) - "libfreebl_hybrid_3.sl" : "libfreebl_pure32_3.sl"; -#else - "libfreebl_hybrid_3.so" : "libfreebl_pure32_3.so"; -#endif + if (!name) { + PR_SetError(PR_LOAD_LIBRARY_ERROR, 0); + return PR_FAILURE; + } handle = bl_LoadLibrary(name); if (handle) { @@ -1373,3 +1403,231 @@ ECDSA_SignDigestWithSeed(ECPrivateKey * key, SECItem * signature, seed, seedlen ); } +/* ============== New for 3.008 =============================== */ + +AESContext * +AES_AllocateContext(void) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return NULL; + return (vector->p_AES_AllocateContext)(); +} + +AESKeyWrapContext * +AESKeyWrap_AllocateContext(void) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return NULL; + return (vector->p_AESKeyWrap_AllocateContext)(); +} + +DESContext * +DES_AllocateContext(void) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return NULL; + return (vector->p_DES_AllocateContext)(); +} + +RC2Context * +RC2_AllocateContext(void) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return NULL; + return (vector->p_RC2_AllocateContext)(); +} + +RC4Context * +RC4_AllocateContext(void) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return NULL; + return (vector->p_RC4_AllocateContext)(); +} + +SECStatus +AES_InitContext(AESContext *cx, const unsigned char *key, + unsigned int keylen, const unsigned char *iv, int mode, + unsigned int encrypt, unsigned int blocklen) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return SECFailure; + return (vector->p_AES_InitContext)(cx, key, keylen, iv, mode, encrypt, + blocklen); +} + +SECStatus +AESKeyWrap_InitContext(AESKeyWrapContext *cx, const unsigned char *key, + unsigned int keylen, const unsigned char *iv, int mode, + unsigned int encrypt, unsigned int blocklen) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return SECFailure; + return (vector->p_AESKeyWrap_InitContext)(cx, key, keylen, iv, mode, + encrypt, blocklen); +} + +SECStatus +DES_InitContext(DESContext *cx, const unsigned char *key, + unsigned int keylen, const unsigned char *iv, int mode, + unsigned int encrypt, unsigned int xtra) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return SECFailure; + return (vector->p_DES_InitContext)(cx, key, keylen, iv, mode, encrypt, xtra); +} + +SECStatus +RC2_InitContext(RC2Context *cx, const unsigned char *key, + unsigned int keylen, const unsigned char *iv, int mode, + unsigned int effectiveKeyLen, unsigned int xtra) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return SECFailure; + return (vector->p_RC2_InitContext)(cx, key, keylen, iv, mode, + effectiveKeyLen, xtra); +} + +SECStatus +RC4_InitContext(RC4Context *cx, const unsigned char *key, + unsigned int keylen, const unsigned char *x1, int x2, + unsigned int x3, unsigned int x4) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return SECFailure; + return (vector->p_RC4_InitContext)(cx, key, keylen, x1, x2, x3, x4); +} + +void +MD2_Clone(MD2Context *dest, MD2Context *src) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return; + (vector->p_MD2_Clone)(dest, src); +} + +void +MD5_Clone(MD5Context *dest, MD5Context *src) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return; + (vector->p_MD5_Clone)(dest, src); +} + +void +SHA1_Clone(SHA1Context *dest, SHA1Context *src) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return; + (vector->p_SHA1_Clone)(dest, src); +} + +void +SHA256_Clone(SHA256Context *dest, SHA256Context *src) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return; + (vector->p_SHA256_Clone)(dest, src); +} + +void +SHA384_Clone(SHA384Context *dest, SHA384Context *src) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return; + (vector->p_SHA384_Clone)(dest, src); +} + +void +SHA512_Clone(SHA512Context *dest, SHA512Context *src) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return; + (vector->p_SHA512_Clone)(dest, src); +} + +SECStatus +TLS_PRF(const SECItem *secret, const char *label, + SECItem *seed, SECItem *result, PRBool isFIPS) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return SECFailure; + return (vector->p_TLS_PRF)(secret, label, seed, result, isFIPS); +} + +const SECHashObject * +HASH_GetRawHashObject(HASH_HashType hashType) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return NULL; + return (vector->p_HASH_GetRawHashObject)(hashType); +} + + +void +HMAC_Destroy(HMACContext *cx, PRBool freeit) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return; + (vector->p_HMAC_Destroy)(cx, freeit); +} + +HMACContext * +HMAC_Create(const SECHashObject *hashObj, const unsigned char *secret, + unsigned int secret_len, PRBool isFIPS) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return NULL; + return (vector->p_HMAC_Create)(hashObj, secret, secret_len, isFIPS); +} + +SECStatus +HMAC_Init(HMACContext *cx, const SECHashObject *hashObj, + const unsigned char *secret, unsigned int secret_len, PRBool isFIPS) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return SECFailure; + return (vector->p_HMAC_Init)(cx, hashObj, secret, secret_len, isFIPS); +} + +void +HMAC_Begin(HMACContext *cx) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return; + (vector->p_HMAC_Begin)(cx); +} + +void +HMAC_Update(HMACContext *cx, const unsigned char *data, unsigned int data_len) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return; + (vector->p_HMAC_Update)(cx, data, data_len); +} + +SECStatus +HMAC_Finish(HMACContext *cx, unsigned char *result, unsigned int *result_len, + unsigned int max_result_len) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return SECFailure; + return (vector->p_HMAC_Finish)(cx, result, result_len, max_result_len); +} + +HMACContext * +HMAC_Clone(HMACContext *cx) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return NULL; + return (vector->p_HMAC_Clone)(cx); +} + +void +RNG_SystemInfoForRNG(void) +{ + if (!vector && PR_SUCCESS != freebl_RunLoaderOnce()) + return ; + (vector->p_RNG_SystemInfoForRNG)(); + +} diff --git a/security/nss/lib/freebl/loader.h b/security/nss/lib/freebl/loader.h index 2bd4a93e4..89bab5401 100644 --- a/security/nss/lib/freebl/loader.h +++ b/security/nss/lib/freebl/loader.h @@ -44,7 +44,7 @@ #include "blapi.h" -#define FREEBL_VERSION 0x0307 +#define FREEBL_VERSION 0x0308 struct FREEBLVectorStr { @@ -377,6 +377,78 @@ struct FREEBLVectorStr { /* Version 3.007 came to here */ + SECStatus (* p_AES_InitContext)(AESContext *cx, + const unsigned char *key, + unsigned int keylen, + const unsigned char *iv, + int mode, + unsigned int encrypt, + unsigned int blocklen); + SECStatus (* p_AESKeyWrap_InitContext)(AESKeyWrapContext *cx, + const unsigned char *key, + unsigned int keylen, + const unsigned char *iv, + int mode, + unsigned int encrypt, + unsigned int blocklen); + SECStatus (* p_DES_InitContext)(DESContext *cx, + const unsigned char *key, + unsigned int keylen, + const unsigned char *iv, + int mode, + unsigned int encrypt, + unsigned int ); + SECStatus (* p_RC2_InitContext)(RC2Context *cx, + const unsigned char *key, + unsigned int keylen, + const unsigned char *iv, + int mode, + unsigned int effectiveKeyLen, + unsigned int ); + SECStatus (* p_RC4_InitContext)(RC4Context *cx, + const unsigned char *key, + unsigned int keylen, + const unsigned char *, + int, + unsigned int , + unsigned int ); + + AESContext *(*p_AES_AllocateContext)(void); + AESKeyWrapContext *(*p_AESKeyWrap_AllocateContext)(void); + DESContext *(*p_DES_AllocateContext)(void); + RC2Context *(*p_RC2_AllocateContext)(void); + RC4Context *(*p_RC4_AllocateContext)(void); + + void (* p_MD2_Clone)(MD2Context *dest, MD2Context *src); + void (* p_MD5_Clone)(MD5Context *dest, MD5Context *src); + void (* p_SHA1_Clone)(SHA1Context *dest, SHA1Context *src); + void (* p_SHA256_Clone)(SHA256Context *dest, SHA256Context *src); + void (* p_SHA384_Clone)(SHA384Context *dest, SHA384Context *src); + void (* p_SHA512_Clone)(SHA512Context *dest, SHA512Context *src); + + SECStatus (* p_TLS_PRF)(const SECItem *secret, const char *label, + SECItem *seed, SECItem *result, PRBool isFIPS); + + const SECHashObject *(* p_HASH_GetRawHashObject)(HASH_HashType hashType); + + HMACContext * (* p_HMAC_Create)(const SECHashObject *hashObj, + const unsigned char *secret, + unsigned int secret_len, PRBool isFIPS); + SECStatus (* p_HMAC_Init)(HMACContext *cx, const SECHashObject *hash_obj, + const unsigned char *secret, + unsigned int secret_len, PRBool isFIPS); + void (* p_HMAC_Begin)(HMACContext *cx); + void (* p_HMAC_Update)(HMACContext *cx, const unsigned char *data, + unsigned int data_len); + HMACContext * (* p_HMAC_Clone)(HMACContext *cx); + SECStatus (* p_HMAC_Finish)(HMACContext *cx, unsigned char *result, + unsigned int *result_len, + unsigned int max_result_len); + void (* p_HMAC_Destroy)(HMACContext *cx, PRBool freeit); + + void (* p_RNG_SystemInfoForRNG)(void); + + /* Version 3.008 came to here */ }; typedef struct FREEBLVectorStr FREEBLVector; diff --git a/security/nss/lib/freebl/manifest.mn b/security/nss/lib/freebl/manifest.mn index d5538b045..787c7fbec 100644 --- a/security/nss/lib/freebl/manifest.mn +++ b/security/nss/lib/freebl/manifest.mn @@ -21,8 +21,7 @@ # # Contributor(s): # Dr Vipul Gupta <vipul.gupta@sun.com> and -# Douglas Stebila <douglas@stebila.ca>, Sun Microsystems -# Laboratories +# Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or @@ -37,25 +36,48 @@ # the terms of any one of the MPL, the GPL or the LGPL. # # ***** END LICENSE BLOCK ***** + +# NOTE: any ifdefs in this file must be defined on the gmake command line +# (if anywhere). They cannot come from Makefile or config.mk + CORE_DEPTH = ../../.. MODULE = nss -ifndef FREEBL_RECURSIVE_BUILD - LIBRARY_NAME = freebl -else - ifdef USE_PURE_32 - CORE_DEPTH = ../../../.. - LIBRARY_NAME = freebl_pure32 - else - LIBRARY_NAME = freebl_hybrid +LIBRARY_NAME = freebl +LIBRARY_VERSION = 3 + +ifdef FREEBL_CHILD_BUILD + ifdef USE_ABI32_INT32 + LIBRARY_NAME = freebl_32int + endif + ifdef USE_ABI32_INT64 + LIBRARY_NAME = freebl_32int64 + endif + ifdef USE_ABI32_FPU + LIBRARY_NAME = freebl_32fpu + endif + ifdef USE_ABI64_INT + LIBRARY_NAME = freebl_64int endif + ifdef USE_ABI64_FPU + LIBRARY_NAME = freebl_64fpu + endif +endif + +# if the library name contains _, we prefix the version with _ +ifneq (,$(findstring _,$(LIBRARY_NAME))) + LIBRARY_VERSION := _$(LIBRARY_VERSION) endif -# same version as rest of freebl -LIBRARY_VERSION = _3 +MAPFILE_SOURCE = freebl.def +MAPFILE = $(OBJDIR)/$(LIBRARY_NAME).def + +SOFTOKEN_LIBRARY_VERSION = 3 -DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" +DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" \ + -DSHLIB_VERSION=\"$(LIBRARY_VERSION)\" \ + -DSOFTOKEN_SHLIB_VERSION=\"$(SOFTOKEN_LIBRARY_VERSION)\" REQUIRES = @@ -66,6 +88,7 @@ EXPORTS = \ $(NULL) PRIVATE_EXPORTS = \ + alghmac.h \ blapi.h \ secmpi.h \ secrng.h \ @@ -76,6 +99,8 @@ PRIVATE_EXPORTS = \ MPI_HDRS = mpi-config.h mpi.h mpi-priv.h mplogic.h mpprime.h logtab.h mp_gf2m.h MPI_SRCS = mpprime.c mpmontg.c mplogic.c mpi.c mp_gf2m.c + + ECL_HDRS = ecl-exp.h ecl.h ec2.h ecp.h ecl-priv.h ifdef NSS_ENABLE_ECC ECL_SRCS = ecl.c ecl_curve.c ecl_mult.c ecl_gf.c \ @@ -87,15 +112,20 @@ ECL_SRCS = ecl.c ecl_curve.c ecl_mult.c ecl_gf.c \ else ECL_SRCS = $(NULL) endif +SHA_SRCS = sha_fast.c +MPCPU_SRCS = mpcpucache.c CSRCS = \ + freeblver.c \ ldvector.c \ prng_fips1861.c \ sysrand.c \ - sha_fast.c \ + $(SHA_SRCS) \ md2.c \ md5.c \ sha512.c \ + alghmac.c \ + rawhash.c \ alg2268.c \ arcfour.c \ arcfive.c \ @@ -109,13 +139,16 @@ CSRCS = \ dsa.c \ rsa.c \ shvfy.c \ + tlsprfalg.c \ $(MPI_SRCS) \ + $(MPCPU_SRCS) \ $(ECL_SRCS) \ $(NULL) ALL_CSRCS := $(CSRCS) ALL_HDRS = \ + alghmac.h \ blapi.h \ blapit.h \ des.h \ @@ -129,6 +162,7 @@ ALL_HDRS = \ vis_proto.h \ $(NULL) + ifdef NSS_ENABLE_ECC DEFINES += -DNSS_ENABLE_ECC endif diff --git a/security/nss/lib/freebl/md2.c b/security/nss/lib/freebl/md2.c index 6dc990a42..ddc7a9d7e 100644 --- a/security/nss/lib/freebl/md2.c +++ b/security/nss/lib/freebl/md2.c @@ -289,3 +289,8 @@ MD2_Resurrect(unsigned char *space, void *arg) memcpy(cx, space, sizeof(*cx)); return cx; } + +void MD2_Clone(MD2Context *dest, MD2Context *src) +{ + memcpy(dest, src, sizeof *dest); +} diff --git a/security/nss/lib/freebl/md5.c b/security/nss/lib/freebl/md5.c index f5b99b2f0..fbcee7f46 100644 --- a/security/nss/lib/freebl/md5.c +++ b/security/nss/lib/freebl/md5.c @@ -229,15 +229,12 @@ SECStatus MD5_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length) { unsigned int len; - MD5Context *cx = MD5_NewContext(); - if (cx == NULL) { - PORT_SetError(PR_OUT_OF_MEMORY_ERROR); - return SECFailure; - } - MD5_Begin(cx); - MD5_Update(cx, src, src_length); - MD5_End(cx, dest, &len, MD5_HASH_LEN); - MD5_DestroyContext(cx, PR_TRUE); + MD5Context cx; + + MD5_Begin(&cx); + MD5_Update(&cx, src, src_length); + MD5_End(&cx, dest, &len, MD5_HASH_LEN); +/* memset(&cx, 0, sizeof cx); */ return SECSuccess; } @@ -256,8 +253,9 @@ MD5_NewContext(void) void MD5_DestroyContext(MD5Context *cx, PRBool freeit) { +/* memset(cx, 0, sizeof *cx); */ if (freeit) { - PORT_ZFree(cx, sizeof(MD5Context)); + PORT_Free(cx); } } @@ -266,7 +264,7 @@ MD5_Begin(MD5Context *cx) { cx->lsbInput = 0; cx->msbInput = 0; - memset(cx->inBuf, 0, sizeof(cx->inBuf)); +/* memset(cx->inBuf, 0, sizeof(cx->inBuf)); */ cx->cv[0] = CV0_1; cx->cv[1] = CV0_2; cx->cv[2] = CV0_3; @@ -585,6 +583,11 @@ MD5_Resurrect(unsigned char *space, void *arg) return cx; } +void MD5_Clone(MD5Context *dest, MD5Context *src) +{ + memcpy(dest, src, sizeof *dest); +} + void MD5_TraceState(MD5Context *cx) { diff --git a/security/nss/lib/freebl/mpi/Makefile b/security/nss/lib/freebl/mpi/Makefile index c28002701..3c780f5ac 100644 --- a/security/nss/lib/freebl/mpi/Makefile +++ b/security/nss/lib/freebl/mpi/Makefile @@ -89,7 +89,8 @@ VERS=1.7p6 ## ## This is the list of source files that need to be packed into ## the distribution file -SRCS= mpi.c mpprime.c mplogic.c mp_gf2m.c mpmontg.c mpi-test.c primes.c tests/ \ +SRCS= mpi.c mpprime.c mplogic.c mp_gf2m.c mpmontg.c mpi-test.c primes.c \ + mpcpucache.c tests/ \ utils/gcd.c utils/invmod.c utils/lap.c \ utils/ptab.pl utils/sieve.c utils/isprime.c\ utils/dec2hex.c utils/hex2dec.c utils/bbs_rand.c \ diff --git a/security/nss/lib/freebl/mpi/mp_comba.c b/security/nss/lib/freebl/mpi/mp_comba.c new file mode 100644 index 000000000..afac82a74 --- /dev/null +++ b/security/nss/lib/freebl/mpi/mp_comba.c @@ -0,0 +1,1306 @@ +/* + * The below file is derived from TFM v0.03. + * It contains code from fp_mul_comba.c and + * fp_sqr_comba.c, which contained the following license. + * + * Right now, the assembly in this file limits + * this code to AMD 64. + * + * This file is public domain. + */ + +/* TomsFastMath, a fast ISO C bignum library. + * + * This project is meant to fill in where LibTomMath + * falls short. That is speed ;-) + * + * This project is public domain and free for all purposes. + * + * Tom St Denis, tomstdenis@iahu.ca + */ + + +#include "mpi-priv.h" + + + +/* clamp digits */ +#define mp_clamp(a) { while ((a)->used && (a)->dp[(a)->used-1] == 0) --((a)->used); (a)->sign = (a)->used ? (a)->sign : ZPOS; } + +/* anything you need at the start */ +#define COMBA_START + +/* clear the chaining variables */ +#define COMBA_CLEAR \ + c0 = c1 = c2 = 0; + +/* forward the carry to the next digit */ +#define COMBA_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +/* anything you need at the end */ +#define COMBA_FINI + +/* this should multiply i and j */ +#define MULADD(i, j) \ +__asm__ ( \ + "movq %6,%%rax \n\t" \ + "mulq %7 \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j) :"%rax","%rdx","%cc"); + + + + +/* sqr macros only */ +#define CLEAR_CARRY \ + c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define CARRY_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +#define SQRADD(i, j) \ +__asm__ ( \ + "movq %6,%%rax \n\t" \ + "mulq %%rax \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i) :"%rax","%rdx","%cc"); + +#define SQRADD2(i, j) \ +__asm__ ( \ + "movq %6,%%rax \n\t" \ + "mulq %7 \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j) :"%rax","%rdx","%cc"); + +#define SQRADDSC(i, j) \ +__asm__ ( \ + "movq %6,%%rax \n\t" \ + "mulq %7 \n\t" \ + "movq %%rax,%0 \n\t" \ + "movq %%rdx,%1 \n\t" \ + "xorq %2,%2 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%rax","%rdx","%cc"); + +#define SQRADDAC(i, j) \ +__asm__ ( \ + "movq %6,%%rax \n\t" \ + "mulq %7 \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%rax","%rdx","%cc"); + +#define SQRADDDB \ +__asm__ ( \ + "addq %3,%0 \n\t" \ + "adcq %4,%1 \n\t" \ + "adcq %5,%2 \n\t" \ + "addq %3,%0 \n\t" \ + "adcq %4,%1 \n\t" \ + "adcq %5,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2), "=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(c0), "1"(c1), "2"(c2), "3"(sc0), "4"(sc1), "5"(sc2) : "%cc"); + + + + + +void s_mp_mul_comba_4(const mp_int *A, const mp_int *B, mp_int *C) +{ + mp_digit c0, c1, c2, at[8]; + + memcpy(at, A->dp, 4 * sizeof(mp_digit)); + memcpy(at+4, B->dp, 4 * sizeof(mp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[4]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[5]); MULADD(at[1], at[4]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[6]); MULADD(at[1], at[5]); MULADD(at[2], at[4]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[7]); MULADD(at[1], at[6]); MULADD(at[2], at[5]); MULADD(at[3], at[4]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[1], at[7]); MULADD(at[2], at[6]); MULADD(at[3], at[5]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[2], at[7]); MULADD(at[3], at[6]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[3], at[7]); + COMBA_STORE(C->dp[6]); + COMBA_STORE2(C->dp[7]); + C->used = 8; + C->sign = A->sign ^ B->sign; + mp_clamp(C); + COMBA_FINI; +} + +void s_mp_mul_comba_8(const mp_int *A, const mp_int *B, mp_int *C) +{ + mp_digit c0, c1, c2, at[16]; + + memcpy(at, A->dp, 8 * sizeof(mp_digit)); + memcpy(at+8, B->dp, 8 * sizeof(mp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[8]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[9]); MULADD(at[1], at[8]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[10]); MULADD(at[1], at[9]); MULADD(at[2], at[8]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[11]); MULADD(at[1], at[10]); MULADD(at[2], at[9]); MULADD(at[3], at[8]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[12]); MULADD(at[1], at[11]); MULADD(at[2], at[10]); MULADD(at[3], at[9]); MULADD(at[4], at[8]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[13]); MULADD(at[1], at[12]); MULADD(at[2], at[11]); MULADD(at[3], at[10]); MULADD(at[4], at[9]); MULADD(at[5], at[8]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[14]); MULADD(at[1], at[13]); MULADD(at[2], at[12]); MULADD(at[3], at[11]); MULADD(at[4], at[10]); MULADD(at[5], at[9]); MULADD(at[6], at[8]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[15]); MULADD(at[1], at[14]); MULADD(at[2], at[13]); MULADD(at[3], at[12]); MULADD(at[4], at[11]); MULADD(at[5], at[10]); MULADD(at[6], at[9]); MULADD(at[7], at[8]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[1], at[15]); MULADD(at[2], at[14]); MULADD(at[3], at[13]); MULADD(at[4], at[12]); MULADD(at[5], at[11]); MULADD(at[6], at[10]); MULADD(at[7], at[9]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[2], at[15]); MULADD(at[3], at[14]); MULADD(at[4], at[13]); MULADD(at[5], at[12]); MULADD(at[6], at[11]); MULADD(at[7], at[10]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[3], at[15]); MULADD(at[4], at[14]); MULADD(at[5], at[13]); MULADD(at[6], at[12]); MULADD(at[7], at[11]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[4], at[15]); MULADD(at[5], at[14]); MULADD(at[6], at[13]); MULADD(at[7], at[12]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[5], at[15]); MULADD(at[6], at[14]); MULADD(at[7], at[13]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[6], at[15]); MULADD(at[7], at[14]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[7], at[15]); + COMBA_STORE(C->dp[14]); + COMBA_STORE2(C->dp[15]); + C->used = 16; + C->sign = A->sign ^ B->sign; + mp_clamp(C); + COMBA_FINI; +} + +void s_mp_mul_comba_16(const mp_int *A, const mp_int *B, mp_int *C) +{ + mp_digit c0, c1, c2, at[32]; + + memcpy(at, A->dp, 16 * sizeof(mp_digit)); + memcpy(at+16, B->dp, 16 * sizeof(mp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[16]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[17]); MULADD(at[1], at[16]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[18]); MULADD(at[1], at[17]); MULADD(at[2], at[16]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[19]); MULADD(at[1], at[18]); MULADD(at[2], at[17]); MULADD(at[3], at[16]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[20]); MULADD(at[1], at[19]); MULADD(at[2], at[18]); MULADD(at[3], at[17]); MULADD(at[4], at[16]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[21]); MULADD(at[1], at[20]); MULADD(at[2], at[19]); MULADD(at[3], at[18]); MULADD(at[4], at[17]); MULADD(at[5], at[16]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[22]); MULADD(at[1], at[21]); MULADD(at[2], at[20]); MULADD(at[3], at[19]); MULADD(at[4], at[18]); MULADD(at[5], at[17]); MULADD(at[6], at[16]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[23]); MULADD(at[1], at[22]); MULADD(at[2], at[21]); MULADD(at[3], at[20]); MULADD(at[4], at[19]); MULADD(at[5], at[18]); MULADD(at[6], at[17]); MULADD(at[7], at[16]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[24]); MULADD(at[1], at[23]); MULADD(at[2], at[22]); MULADD(at[3], at[21]); MULADD(at[4], at[20]); MULADD(at[5], at[19]); MULADD(at[6], at[18]); MULADD(at[7], at[17]); MULADD(at[8], at[16]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[25]); MULADD(at[1], at[24]); MULADD(at[2], at[23]); MULADD(at[3], at[22]); MULADD(at[4], at[21]); MULADD(at[5], at[20]); MULADD(at[6], at[19]); MULADD(at[7], at[18]); MULADD(at[8], at[17]); MULADD(at[9], at[16]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[26]); MULADD(at[1], at[25]); MULADD(at[2], at[24]); MULADD(at[3], at[23]); MULADD(at[4], at[22]); MULADD(at[5], at[21]); MULADD(at[6], at[20]); MULADD(at[7], at[19]); MULADD(at[8], at[18]); MULADD(at[9], at[17]); MULADD(at[10], at[16]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[27]); MULADD(at[1], at[26]); MULADD(at[2], at[25]); MULADD(at[3], at[24]); MULADD(at[4], at[23]); MULADD(at[5], at[22]); MULADD(at[6], at[21]); MULADD(at[7], at[20]); MULADD(at[8], at[19]); MULADD(at[9], at[18]); MULADD(at[10], at[17]); MULADD(at[11], at[16]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[0], at[28]); MULADD(at[1], at[27]); MULADD(at[2], at[26]); MULADD(at[3], at[25]); MULADD(at[4], at[24]); MULADD(at[5], at[23]); MULADD(at[6], at[22]); MULADD(at[7], at[21]); MULADD(at[8], at[20]); MULADD(at[9], at[19]); MULADD(at[10], at[18]); MULADD(at[11], at[17]); MULADD(at[12], at[16]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[0], at[29]); MULADD(at[1], at[28]); MULADD(at[2], at[27]); MULADD(at[3], at[26]); MULADD(at[4], at[25]); MULADD(at[5], at[24]); MULADD(at[6], at[23]); MULADD(at[7], at[22]); MULADD(at[8], at[21]); MULADD(at[9], at[20]); MULADD(at[10], at[19]); MULADD(at[11], at[18]); MULADD(at[12], at[17]); MULADD(at[13], at[16]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[0], at[30]); MULADD(at[1], at[29]); MULADD(at[2], at[28]); MULADD(at[3], at[27]); MULADD(at[4], at[26]); MULADD(at[5], at[25]); MULADD(at[6], at[24]); MULADD(at[7], at[23]); MULADD(at[8], at[22]); MULADD(at[9], at[21]); MULADD(at[10], at[20]); MULADD(at[11], at[19]); MULADD(at[12], at[18]); MULADD(at[13], at[17]); MULADD(at[14], at[16]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[0], at[31]); MULADD(at[1], at[30]); MULADD(at[2], at[29]); MULADD(at[3], at[28]); MULADD(at[4], at[27]); MULADD(at[5], at[26]); MULADD(at[6], at[25]); MULADD(at[7], at[24]); MULADD(at[8], at[23]); MULADD(at[9], at[22]); MULADD(at[10], at[21]); MULADD(at[11], at[20]); MULADD(at[12], at[19]); MULADD(at[13], at[18]); MULADD(at[14], at[17]); MULADD(at[15], at[16]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[1], at[31]); MULADD(at[2], at[30]); MULADD(at[3], at[29]); MULADD(at[4], at[28]); MULADD(at[5], at[27]); MULADD(at[6], at[26]); MULADD(at[7], at[25]); MULADD(at[8], at[24]); MULADD(at[9], at[23]); MULADD(at[10], at[22]); MULADD(at[11], at[21]); MULADD(at[12], at[20]); MULADD(at[13], at[19]); MULADD(at[14], at[18]); MULADD(at[15], at[17]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[2], at[31]); MULADD(at[3], at[30]); MULADD(at[4], at[29]); MULADD(at[5], at[28]); MULADD(at[6], at[27]); MULADD(at[7], at[26]); MULADD(at[8], at[25]); MULADD(at[9], at[24]); MULADD(at[10], at[23]); MULADD(at[11], at[22]); MULADD(at[12], at[21]); MULADD(at[13], at[20]); MULADD(at[14], at[19]); MULADD(at[15], at[18]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[3], at[31]); MULADD(at[4], at[30]); MULADD(at[5], at[29]); MULADD(at[6], at[28]); MULADD(at[7], at[27]); MULADD(at[8], at[26]); MULADD(at[9], at[25]); MULADD(at[10], at[24]); MULADD(at[11], at[23]); MULADD(at[12], at[22]); MULADD(at[13], at[21]); MULADD(at[14], at[20]); MULADD(at[15], at[19]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[4], at[31]); MULADD(at[5], at[30]); MULADD(at[6], at[29]); MULADD(at[7], at[28]); MULADD(at[8], at[27]); MULADD(at[9], at[26]); MULADD(at[10], at[25]); MULADD(at[11], at[24]); MULADD(at[12], at[23]); MULADD(at[13], at[22]); MULADD(at[14], at[21]); MULADD(at[15], at[20]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[5], at[31]); MULADD(at[6], at[30]); MULADD(at[7], at[29]); MULADD(at[8], at[28]); MULADD(at[9], at[27]); MULADD(at[10], at[26]); MULADD(at[11], at[25]); MULADD(at[12], at[24]); MULADD(at[13], at[23]); MULADD(at[14], at[22]); MULADD(at[15], at[21]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[6], at[31]); MULADD(at[7], at[30]); MULADD(at[8], at[29]); MULADD(at[9], at[28]); MULADD(at[10], at[27]); MULADD(at[11], at[26]); MULADD(at[12], at[25]); MULADD(at[13], at[24]); MULADD(at[14], at[23]); MULADD(at[15], at[22]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[7], at[31]); MULADD(at[8], at[30]); MULADD(at[9], at[29]); MULADD(at[10], at[28]); MULADD(at[11], at[27]); MULADD(at[12], at[26]); MULADD(at[13], at[25]); MULADD(at[14], at[24]); MULADD(at[15], at[23]); + COMBA_STORE(C->dp[22]); + /* 23 */ + COMBA_FORWARD; + MULADD(at[8], at[31]); MULADD(at[9], at[30]); MULADD(at[10], at[29]); MULADD(at[11], at[28]); MULADD(at[12], at[27]); MULADD(at[13], at[26]); MULADD(at[14], at[25]); MULADD(at[15], at[24]); + COMBA_STORE(C->dp[23]); + /* 24 */ + COMBA_FORWARD; + MULADD(at[9], at[31]); MULADD(at[10], at[30]); MULADD(at[11], at[29]); MULADD(at[12], at[28]); MULADD(at[13], at[27]); MULADD(at[14], at[26]); MULADD(at[15], at[25]); + COMBA_STORE(C->dp[24]); + /* 25 */ + COMBA_FORWARD; + MULADD(at[10], at[31]); MULADD(at[11], at[30]); MULADD(at[12], at[29]); MULADD(at[13], at[28]); MULADD(at[14], at[27]); MULADD(at[15], at[26]); + COMBA_STORE(C->dp[25]); + /* 26 */ + COMBA_FORWARD; + MULADD(at[11], at[31]); MULADD(at[12], at[30]); MULADD(at[13], at[29]); MULADD(at[14], at[28]); MULADD(at[15], at[27]); + COMBA_STORE(C->dp[26]); + /* 27 */ + COMBA_FORWARD; + MULADD(at[12], at[31]); MULADD(at[13], at[30]); MULADD(at[14], at[29]); MULADD(at[15], at[28]); + COMBA_STORE(C->dp[27]); + /* 28 */ + COMBA_FORWARD; + MULADD(at[13], at[31]); MULADD(at[14], at[30]); MULADD(at[15], at[29]); + COMBA_STORE(C->dp[28]); + /* 29 */ + COMBA_FORWARD; + MULADD(at[14], at[31]); MULADD(at[15], at[30]); + COMBA_STORE(C->dp[29]); + /* 30 */ + COMBA_FORWARD; + MULADD(at[15], at[31]); + COMBA_STORE(C->dp[30]); + COMBA_STORE2(C->dp[31]); + C->used = 32; + C->sign = A->sign ^ B->sign; + mp_clamp(C); + COMBA_FINI; +} + +void s_mp_mul_comba_32(const mp_int *A, const mp_int *B, mp_int *C) +{ + mp_digit c0, c1, c2, at[64]; + + memcpy(at, A->dp, 32 * sizeof(mp_digit)); + memcpy(at+32, B->dp, 32 * sizeof(mp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[32]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[33]); MULADD(at[1], at[32]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[34]); MULADD(at[1], at[33]); MULADD(at[2], at[32]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[35]); MULADD(at[1], at[34]); MULADD(at[2], at[33]); MULADD(at[3], at[32]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[36]); MULADD(at[1], at[35]); MULADD(at[2], at[34]); MULADD(at[3], at[33]); MULADD(at[4], at[32]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[37]); MULADD(at[1], at[36]); MULADD(at[2], at[35]); MULADD(at[3], at[34]); MULADD(at[4], at[33]); MULADD(at[5], at[32]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[38]); MULADD(at[1], at[37]); MULADD(at[2], at[36]); MULADD(at[3], at[35]); MULADD(at[4], at[34]); MULADD(at[5], at[33]); MULADD(at[6], at[32]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[39]); MULADD(at[1], at[38]); MULADD(at[2], at[37]); MULADD(at[3], at[36]); MULADD(at[4], at[35]); MULADD(at[5], at[34]); MULADD(at[6], at[33]); MULADD(at[7], at[32]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[40]); MULADD(at[1], at[39]); MULADD(at[2], at[38]); MULADD(at[3], at[37]); MULADD(at[4], at[36]); MULADD(at[5], at[35]); MULADD(at[6], at[34]); MULADD(at[7], at[33]); MULADD(at[8], at[32]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[41]); MULADD(at[1], at[40]); MULADD(at[2], at[39]); MULADD(at[3], at[38]); MULADD(at[4], at[37]); MULADD(at[5], at[36]); MULADD(at[6], at[35]); MULADD(at[7], at[34]); MULADD(at[8], at[33]); MULADD(at[9], at[32]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[42]); MULADD(at[1], at[41]); MULADD(at[2], at[40]); MULADD(at[3], at[39]); MULADD(at[4], at[38]); MULADD(at[5], at[37]); MULADD(at[6], at[36]); MULADD(at[7], at[35]); MULADD(at[8], at[34]); MULADD(at[9], at[33]); MULADD(at[10], at[32]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[43]); MULADD(at[1], at[42]); MULADD(at[2], at[41]); MULADD(at[3], at[40]); MULADD(at[4], at[39]); MULADD(at[5], at[38]); MULADD(at[6], at[37]); MULADD(at[7], at[36]); MULADD(at[8], at[35]); MULADD(at[9], at[34]); MULADD(at[10], at[33]); MULADD(at[11], at[32]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[0], at[44]); MULADD(at[1], at[43]); MULADD(at[2], at[42]); MULADD(at[3], at[41]); MULADD(at[4], at[40]); MULADD(at[5], at[39]); MULADD(at[6], at[38]); MULADD(at[7], at[37]); MULADD(at[8], at[36]); MULADD(at[9], at[35]); MULADD(at[10], at[34]); MULADD(at[11], at[33]); MULADD(at[12], at[32]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[0], at[45]); MULADD(at[1], at[44]); MULADD(at[2], at[43]); MULADD(at[3], at[42]); MULADD(at[4], at[41]); MULADD(at[5], at[40]); MULADD(at[6], at[39]); MULADD(at[7], at[38]); MULADD(at[8], at[37]); MULADD(at[9], at[36]); MULADD(at[10], at[35]); MULADD(at[11], at[34]); MULADD(at[12], at[33]); MULADD(at[13], at[32]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[0], at[46]); MULADD(at[1], at[45]); MULADD(at[2], at[44]); MULADD(at[3], at[43]); MULADD(at[4], at[42]); MULADD(at[5], at[41]); MULADD(at[6], at[40]); MULADD(at[7], at[39]); MULADD(at[8], at[38]); MULADD(at[9], at[37]); MULADD(at[10], at[36]); MULADD(at[11], at[35]); MULADD(at[12], at[34]); MULADD(at[13], at[33]); MULADD(at[14], at[32]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[0], at[47]); MULADD(at[1], at[46]); MULADD(at[2], at[45]); MULADD(at[3], at[44]); MULADD(at[4], at[43]); MULADD(at[5], at[42]); MULADD(at[6], at[41]); MULADD(at[7], at[40]); MULADD(at[8], at[39]); MULADD(at[9], at[38]); MULADD(at[10], at[37]); MULADD(at[11], at[36]); MULADD(at[12], at[35]); MULADD(at[13], at[34]); MULADD(at[14], at[33]); MULADD(at[15], at[32]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[0], at[48]); MULADD(at[1], at[47]); MULADD(at[2], at[46]); MULADD(at[3], at[45]); MULADD(at[4], at[44]); MULADD(at[5], at[43]); MULADD(at[6], at[42]); MULADD(at[7], at[41]); MULADD(at[8], at[40]); MULADD(at[9], at[39]); MULADD(at[10], at[38]); MULADD(at[11], at[37]); MULADD(at[12], at[36]); MULADD(at[13], at[35]); MULADD(at[14], at[34]); MULADD(at[15], at[33]); MULADD(at[16], at[32]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[0], at[49]); MULADD(at[1], at[48]); MULADD(at[2], at[47]); MULADD(at[3], at[46]); MULADD(at[4], at[45]); MULADD(at[5], at[44]); MULADD(at[6], at[43]); MULADD(at[7], at[42]); MULADD(at[8], at[41]); MULADD(at[9], at[40]); MULADD(at[10], at[39]); MULADD(at[11], at[38]); MULADD(at[12], at[37]); MULADD(at[13], at[36]); MULADD(at[14], at[35]); MULADD(at[15], at[34]); MULADD(at[16], at[33]); MULADD(at[17], at[32]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[0], at[50]); MULADD(at[1], at[49]); MULADD(at[2], at[48]); MULADD(at[3], at[47]); MULADD(at[4], at[46]); MULADD(at[5], at[45]); MULADD(at[6], at[44]); MULADD(at[7], at[43]); MULADD(at[8], at[42]); MULADD(at[9], at[41]); MULADD(at[10], at[40]); MULADD(at[11], at[39]); MULADD(at[12], at[38]); MULADD(at[13], at[37]); MULADD(at[14], at[36]); MULADD(at[15], at[35]); MULADD(at[16], at[34]); MULADD(at[17], at[33]); MULADD(at[18], at[32]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[0], at[51]); MULADD(at[1], at[50]); MULADD(at[2], at[49]); MULADD(at[3], at[48]); MULADD(at[4], at[47]); MULADD(at[5], at[46]); MULADD(at[6], at[45]); MULADD(at[7], at[44]); MULADD(at[8], at[43]); MULADD(at[9], at[42]); MULADD(at[10], at[41]); MULADD(at[11], at[40]); MULADD(at[12], at[39]); MULADD(at[13], at[38]); MULADD(at[14], at[37]); MULADD(at[15], at[36]); MULADD(at[16], at[35]); MULADD(at[17], at[34]); MULADD(at[18], at[33]); MULADD(at[19], at[32]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[0], at[52]); MULADD(at[1], at[51]); MULADD(at[2], at[50]); MULADD(at[3], at[49]); MULADD(at[4], at[48]); MULADD(at[5], at[47]); MULADD(at[6], at[46]); MULADD(at[7], at[45]); MULADD(at[8], at[44]); MULADD(at[9], at[43]); MULADD(at[10], at[42]); MULADD(at[11], at[41]); MULADD(at[12], at[40]); MULADD(at[13], at[39]); MULADD(at[14], at[38]); MULADD(at[15], at[37]); MULADD(at[16], at[36]); MULADD(at[17], at[35]); MULADD(at[18], at[34]); MULADD(at[19], at[33]); MULADD(at[20], at[32]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[0], at[53]); MULADD(at[1], at[52]); MULADD(at[2], at[51]); MULADD(at[3], at[50]); MULADD(at[4], at[49]); MULADD(at[5], at[48]); MULADD(at[6], at[47]); MULADD(at[7], at[46]); MULADD(at[8], at[45]); MULADD(at[9], at[44]); MULADD(at[10], at[43]); MULADD(at[11], at[42]); MULADD(at[12], at[41]); MULADD(at[13], at[40]); MULADD(at[14], at[39]); MULADD(at[15], at[38]); MULADD(at[16], at[37]); MULADD(at[17], at[36]); MULADD(at[18], at[35]); MULADD(at[19], at[34]); MULADD(at[20], at[33]); MULADD(at[21], at[32]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[0], at[54]); MULADD(at[1], at[53]); MULADD(at[2], at[52]); MULADD(at[3], at[51]); MULADD(at[4], at[50]); MULADD(at[5], at[49]); MULADD(at[6], at[48]); MULADD(at[7], at[47]); MULADD(at[8], at[46]); MULADD(at[9], at[45]); MULADD(at[10], at[44]); MULADD(at[11], at[43]); MULADD(at[12], at[42]); MULADD(at[13], at[41]); MULADD(at[14], at[40]); MULADD(at[15], at[39]); MULADD(at[16], at[38]); MULADD(at[17], at[37]); MULADD(at[18], at[36]); MULADD(at[19], at[35]); MULADD(at[20], at[34]); MULADD(at[21], at[33]); MULADD(at[22], at[32]); + COMBA_STORE(C->dp[22]); + /* 23 */ + COMBA_FORWARD; + MULADD(at[0], at[55]); MULADD(at[1], at[54]); MULADD(at[2], at[53]); MULADD(at[3], at[52]); MULADD(at[4], at[51]); MULADD(at[5], at[50]); MULADD(at[6], at[49]); MULADD(at[7], at[48]); MULADD(at[8], at[47]); MULADD(at[9], at[46]); MULADD(at[10], at[45]); MULADD(at[11], at[44]); MULADD(at[12], at[43]); MULADD(at[13], at[42]); MULADD(at[14], at[41]); MULADD(at[15], at[40]); MULADD(at[16], at[39]); MULADD(at[17], at[38]); MULADD(at[18], at[37]); MULADD(at[19], at[36]); MULADD(at[20], at[35]); MULADD(at[21], at[34]); MULADD(at[22], at[33]); MULADD(at[23], at[32]); + COMBA_STORE(C->dp[23]); + /* 24 */ + COMBA_FORWARD; + MULADD(at[0], at[56]); MULADD(at[1], at[55]); MULADD(at[2], at[54]); MULADD(at[3], at[53]); MULADD(at[4], at[52]); MULADD(at[5], at[51]); MULADD(at[6], at[50]); MULADD(at[7], at[49]); MULADD(at[8], at[48]); MULADD(at[9], at[47]); MULADD(at[10], at[46]); MULADD(at[11], at[45]); MULADD(at[12], at[44]); MULADD(at[13], at[43]); MULADD(at[14], at[42]); MULADD(at[15], at[41]); MULADD(at[16], at[40]); MULADD(at[17], at[39]); MULADD(at[18], at[38]); MULADD(at[19], at[37]); MULADD(at[20], at[36]); MULADD(at[21], at[35]); MULADD(at[22], at[34]); MULADD(at[23], at[33]); MULADD(at[24], at[32]); + COMBA_STORE(C->dp[24]); + /* 25 */ + COMBA_FORWARD; + MULADD(at[0], at[57]); MULADD(at[1], at[56]); MULADD(at[2], at[55]); MULADD(at[3], at[54]); MULADD(at[4], at[53]); MULADD(at[5], at[52]); MULADD(at[6], at[51]); MULADD(at[7], at[50]); MULADD(at[8], at[49]); MULADD(at[9], at[48]); MULADD(at[10], at[47]); MULADD(at[11], at[46]); MULADD(at[12], at[45]); MULADD(at[13], at[44]); MULADD(at[14], at[43]); MULADD(at[15], at[42]); MULADD(at[16], at[41]); MULADD(at[17], at[40]); MULADD(at[18], at[39]); MULADD(at[19], at[38]); MULADD(at[20], at[37]); MULADD(at[21], at[36]); MULADD(at[22], at[35]); MULADD(at[23], at[34]); MULADD(at[24], at[33]); MULADD(at[25], at[32]); + COMBA_STORE(C->dp[25]); + /* 26 */ + COMBA_FORWARD; + MULADD(at[0], at[58]); MULADD(at[1], at[57]); MULADD(at[2], at[56]); MULADD(at[3], at[55]); MULADD(at[4], at[54]); MULADD(at[5], at[53]); MULADD(at[6], at[52]); MULADD(at[7], at[51]); MULADD(at[8], at[50]); MULADD(at[9], at[49]); MULADD(at[10], at[48]); MULADD(at[11], at[47]); MULADD(at[12], at[46]); MULADD(at[13], at[45]); MULADD(at[14], at[44]); MULADD(at[15], at[43]); MULADD(at[16], at[42]); MULADD(at[17], at[41]); MULADD(at[18], at[40]); MULADD(at[19], at[39]); MULADD(at[20], at[38]); MULADD(at[21], at[37]); MULADD(at[22], at[36]); MULADD(at[23], at[35]); MULADD(at[24], at[34]); MULADD(at[25], at[33]); MULADD(at[26], at[32]); + COMBA_STORE(C->dp[26]); + /* 27 */ + COMBA_FORWARD; + MULADD(at[0], at[59]); MULADD(at[1], at[58]); MULADD(at[2], at[57]); MULADD(at[3], at[56]); MULADD(at[4], at[55]); MULADD(at[5], at[54]); MULADD(at[6], at[53]); MULADD(at[7], at[52]); MULADD(at[8], at[51]); MULADD(at[9], at[50]); MULADD(at[10], at[49]); MULADD(at[11], at[48]); MULADD(at[12], at[47]); MULADD(at[13], at[46]); MULADD(at[14], at[45]); MULADD(at[15], at[44]); MULADD(at[16], at[43]); MULADD(at[17], at[42]); MULADD(at[18], at[41]); MULADD(at[19], at[40]); MULADD(at[20], at[39]); MULADD(at[21], at[38]); MULADD(at[22], at[37]); MULADD(at[23], at[36]); MULADD(at[24], at[35]); MULADD(at[25], at[34]); MULADD(at[26], at[33]); MULADD(at[27], at[32]); + COMBA_STORE(C->dp[27]); + /* 28 */ + COMBA_FORWARD; + MULADD(at[0], at[60]); MULADD(at[1], at[59]); MULADD(at[2], at[58]); MULADD(at[3], at[57]); MULADD(at[4], at[56]); MULADD(at[5], at[55]); MULADD(at[6], at[54]); MULADD(at[7], at[53]); MULADD(at[8], at[52]); MULADD(at[9], at[51]); MULADD(at[10], at[50]); MULADD(at[11], at[49]); MULADD(at[12], at[48]); MULADD(at[13], at[47]); MULADD(at[14], at[46]); MULADD(at[15], at[45]); MULADD(at[16], at[44]); MULADD(at[17], at[43]); MULADD(at[18], at[42]); MULADD(at[19], at[41]); MULADD(at[20], at[40]); MULADD(at[21], at[39]); MULADD(at[22], at[38]); MULADD(at[23], at[37]); MULADD(at[24], at[36]); MULADD(at[25], at[35]); MULADD(at[26], at[34]); MULADD(at[27], at[33]); MULADD(at[28], at[32]); + COMBA_STORE(C->dp[28]); + /* 29 */ + COMBA_FORWARD; + MULADD(at[0], at[61]); MULADD(at[1], at[60]); MULADD(at[2], at[59]); MULADD(at[3], at[58]); MULADD(at[4], at[57]); MULADD(at[5], at[56]); MULADD(at[6], at[55]); MULADD(at[7], at[54]); MULADD(at[8], at[53]); MULADD(at[9], at[52]); MULADD(at[10], at[51]); MULADD(at[11], at[50]); MULADD(at[12], at[49]); MULADD(at[13], at[48]); MULADD(at[14], at[47]); MULADD(at[15], at[46]); MULADD(at[16], at[45]); MULADD(at[17], at[44]); MULADD(at[18], at[43]); MULADD(at[19], at[42]); MULADD(at[20], at[41]); MULADD(at[21], at[40]); MULADD(at[22], at[39]); MULADD(at[23], at[38]); MULADD(at[24], at[37]); MULADD(at[25], at[36]); MULADD(at[26], at[35]); MULADD(at[27], at[34]); MULADD(at[28], at[33]); MULADD(at[29], at[32]); + COMBA_STORE(C->dp[29]); + /* 30 */ + COMBA_FORWARD; + MULADD(at[0], at[62]); MULADD(at[1], at[61]); MULADD(at[2], at[60]); MULADD(at[3], at[59]); MULADD(at[4], at[58]); MULADD(at[5], at[57]); MULADD(at[6], at[56]); MULADD(at[7], at[55]); MULADD(at[8], at[54]); MULADD(at[9], at[53]); MULADD(at[10], at[52]); MULADD(at[11], at[51]); MULADD(at[12], at[50]); MULADD(at[13], at[49]); MULADD(at[14], at[48]); MULADD(at[15], at[47]); MULADD(at[16], at[46]); MULADD(at[17], at[45]); MULADD(at[18], at[44]); MULADD(at[19], at[43]); MULADD(at[20], at[42]); MULADD(at[21], at[41]); MULADD(at[22], at[40]); MULADD(at[23], at[39]); MULADD(at[24], at[38]); MULADD(at[25], at[37]); MULADD(at[26], at[36]); MULADD(at[27], at[35]); MULADD(at[28], at[34]); MULADD(at[29], at[33]); MULADD(at[30], at[32]); + COMBA_STORE(C->dp[30]); + /* 31 */ + COMBA_FORWARD; + MULADD(at[0], at[63]); MULADD(at[1], at[62]); MULADD(at[2], at[61]); MULADD(at[3], at[60]); MULADD(at[4], at[59]); MULADD(at[5], at[58]); MULADD(at[6], at[57]); MULADD(at[7], at[56]); MULADD(at[8], at[55]); MULADD(at[9], at[54]); MULADD(at[10], at[53]); MULADD(at[11], at[52]); MULADD(at[12], at[51]); MULADD(at[13], at[50]); MULADD(at[14], at[49]); MULADD(at[15], at[48]); MULADD(at[16], at[47]); MULADD(at[17], at[46]); MULADD(at[18], at[45]); MULADD(at[19], at[44]); MULADD(at[20], at[43]); MULADD(at[21], at[42]); MULADD(at[22], at[41]); MULADD(at[23], at[40]); MULADD(at[24], at[39]); MULADD(at[25], at[38]); MULADD(at[26], at[37]); MULADD(at[27], at[36]); MULADD(at[28], at[35]); MULADD(at[29], at[34]); MULADD(at[30], at[33]); MULADD(at[31], at[32]); + COMBA_STORE(C->dp[31]); + /* 32 */ + COMBA_FORWARD; + MULADD(at[1], at[63]); MULADD(at[2], at[62]); MULADD(at[3], at[61]); MULADD(at[4], at[60]); MULADD(at[5], at[59]); MULADD(at[6], at[58]); MULADD(at[7], at[57]); MULADD(at[8], at[56]); MULADD(at[9], at[55]); MULADD(at[10], at[54]); MULADD(at[11], at[53]); MULADD(at[12], at[52]); MULADD(at[13], at[51]); MULADD(at[14], at[50]); MULADD(at[15], at[49]); MULADD(at[16], at[48]); MULADD(at[17], at[47]); MULADD(at[18], at[46]); MULADD(at[19], at[45]); MULADD(at[20], at[44]); MULADD(at[21], at[43]); MULADD(at[22], at[42]); MULADD(at[23], at[41]); MULADD(at[24], at[40]); MULADD(at[25], at[39]); MULADD(at[26], at[38]); MULADD(at[27], at[37]); MULADD(at[28], at[36]); MULADD(at[29], at[35]); MULADD(at[30], at[34]); MULADD(at[31], at[33]); + COMBA_STORE(C->dp[32]); + /* 33 */ + COMBA_FORWARD; + MULADD(at[2], at[63]); MULADD(at[3], at[62]); MULADD(at[4], at[61]); MULADD(at[5], at[60]); MULADD(at[6], at[59]); MULADD(at[7], at[58]); MULADD(at[8], at[57]); MULADD(at[9], at[56]); MULADD(at[10], at[55]); MULADD(at[11], at[54]); MULADD(at[12], at[53]); MULADD(at[13], at[52]); MULADD(at[14], at[51]); MULADD(at[15], at[50]); MULADD(at[16], at[49]); MULADD(at[17], at[48]); MULADD(at[18], at[47]); MULADD(at[19], at[46]); MULADD(at[20], at[45]); MULADD(at[21], at[44]); MULADD(at[22], at[43]); MULADD(at[23], at[42]); MULADD(at[24], at[41]); MULADD(at[25], at[40]); MULADD(at[26], at[39]); MULADD(at[27], at[38]); MULADD(at[28], at[37]); MULADD(at[29], at[36]); MULADD(at[30], at[35]); MULADD(at[31], at[34]); + COMBA_STORE(C->dp[33]); + /* 34 */ + COMBA_FORWARD; + MULADD(at[3], at[63]); MULADD(at[4], at[62]); MULADD(at[5], at[61]); MULADD(at[6], at[60]); MULADD(at[7], at[59]); MULADD(at[8], at[58]); MULADD(at[9], at[57]); MULADD(at[10], at[56]); MULADD(at[11], at[55]); MULADD(at[12], at[54]); MULADD(at[13], at[53]); MULADD(at[14], at[52]); MULADD(at[15], at[51]); MULADD(at[16], at[50]); MULADD(at[17], at[49]); MULADD(at[18], at[48]); MULADD(at[19], at[47]); MULADD(at[20], at[46]); MULADD(at[21], at[45]); MULADD(at[22], at[44]); MULADD(at[23], at[43]); MULADD(at[24], at[42]); MULADD(at[25], at[41]); MULADD(at[26], at[40]); MULADD(at[27], at[39]); MULADD(at[28], at[38]); MULADD(at[29], at[37]); MULADD(at[30], at[36]); MULADD(at[31], at[35]); + COMBA_STORE(C->dp[34]); + /* 35 */ + COMBA_FORWARD; + MULADD(at[4], at[63]); MULADD(at[5], at[62]); MULADD(at[6], at[61]); MULADD(at[7], at[60]); MULADD(at[8], at[59]); MULADD(at[9], at[58]); MULADD(at[10], at[57]); MULADD(at[11], at[56]); MULADD(at[12], at[55]); MULADD(at[13], at[54]); MULADD(at[14], at[53]); MULADD(at[15], at[52]); MULADD(at[16], at[51]); MULADD(at[17], at[50]); MULADD(at[18], at[49]); MULADD(at[19], at[48]); MULADD(at[20], at[47]); MULADD(at[21], at[46]); MULADD(at[22], at[45]); MULADD(at[23], at[44]); MULADD(at[24], at[43]); MULADD(at[25], at[42]); MULADD(at[26], at[41]); MULADD(at[27], at[40]); MULADD(at[28], at[39]); MULADD(at[29], at[38]); MULADD(at[30], at[37]); MULADD(at[31], at[36]); + COMBA_STORE(C->dp[35]); + /* 36 */ + COMBA_FORWARD; + MULADD(at[5], at[63]); MULADD(at[6], at[62]); MULADD(at[7], at[61]); MULADD(at[8], at[60]); MULADD(at[9], at[59]); MULADD(at[10], at[58]); MULADD(at[11], at[57]); MULADD(at[12], at[56]); MULADD(at[13], at[55]); MULADD(at[14], at[54]); MULADD(at[15], at[53]); MULADD(at[16], at[52]); MULADD(at[17], at[51]); MULADD(at[18], at[50]); MULADD(at[19], at[49]); MULADD(at[20], at[48]); MULADD(at[21], at[47]); MULADD(at[22], at[46]); MULADD(at[23], at[45]); MULADD(at[24], at[44]); MULADD(at[25], at[43]); MULADD(at[26], at[42]); MULADD(at[27], at[41]); MULADD(at[28], at[40]); MULADD(at[29], at[39]); MULADD(at[30], at[38]); MULADD(at[31], at[37]); + COMBA_STORE(C->dp[36]); + /* 37 */ + COMBA_FORWARD; + MULADD(at[6], at[63]); MULADD(at[7], at[62]); MULADD(at[8], at[61]); MULADD(at[9], at[60]); MULADD(at[10], at[59]); MULADD(at[11], at[58]); MULADD(at[12], at[57]); MULADD(at[13], at[56]); MULADD(at[14], at[55]); MULADD(at[15], at[54]); MULADD(at[16], at[53]); MULADD(at[17], at[52]); MULADD(at[18], at[51]); MULADD(at[19], at[50]); MULADD(at[20], at[49]); MULADD(at[21], at[48]); MULADD(at[22], at[47]); MULADD(at[23], at[46]); MULADD(at[24], at[45]); MULADD(at[25], at[44]); MULADD(at[26], at[43]); MULADD(at[27], at[42]); MULADD(at[28], at[41]); MULADD(at[29], at[40]); MULADD(at[30], at[39]); MULADD(at[31], at[38]); + COMBA_STORE(C->dp[37]); + /* 38 */ + COMBA_FORWARD; + MULADD(at[7], at[63]); MULADD(at[8], at[62]); MULADD(at[9], at[61]); MULADD(at[10], at[60]); MULADD(at[11], at[59]); MULADD(at[12], at[58]); MULADD(at[13], at[57]); MULADD(at[14], at[56]); MULADD(at[15], at[55]); MULADD(at[16], at[54]); MULADD(at[17], at[53]); MULADD(at[18], at[52]); MULADD(at[19], at[51]); MULADD(at[20], at[50]); MULADD(at[21], at[49]); MULADD(at[22], at[48]); MULADD(at[23], at[47]); MULADD(at[24], at[46]); MULADD(at[25], at[45]); MULADD(at[26], at[44]); MULADD(at[27], at[43]); MULADD(at[28], at[42]); MULADD(at[29], at[41]); MULADD(at[30], at[40]); MULADD(at[31], at[39]); + COMBA_STORE(C->dp[38]); + /* 39 */ + COMBA_FORWARD; + MULADD(at[8], at[63]); MULADD(at[9], at[62]); MULADD(at[10], at[61]); MULADD(at[11], at[60]); MULADD(at[12], at[59]); MULADD(at[13], at[58]); MULADD(at[14], at[57]); MULADD(at[15], at[56]); MULADD(at[16], at[55]); MULADD(at[17], at[54]); MULADD(at[18], at[53]); MULADD(at[19], at[52]); MULADD(at[20], at[51]); MULADD(at[21], at[50]); MULADD(at[22], at[49]); MULADD(at[23], at[48]); MULADD(at[24], at[47]); MULADD(at[25], at[46]); MULADD(at[26], at[45]); MULADD(at[27], at[44]); MULADD(at[28], at[43]); MULADD(at[29], at[42]); MULADD(at[30], at[41]); MULADD(at[31], at[40]); + COMBA_STORE(C->dp[39]); + /* 40 */ + COMBA_FORWARD; + MULADD(at[9], at[63]); MULADD(at[10], at[62]); MULADD(at[11], at[61]); MULADD(at[12], at[60]); MULADD(at[13], at[59]); MULADD(at[14], at[58]); MULADD(at[15], at[57]); MULADD(at[16], at[56]); MULADD(at[17], at[55]); MULADD(at[18], at[54]); MULADD(at[19], at[53]); MULADD(at[20], at[52]); MULADD(at[21], at[51]); MULADD(at[22], at[50]); MULADD(at[23], at[49]); MULADD(at[24], at[48]); MULADD(at[25], at[47]); MULADD(at[26], at[46]); MULADD(at[27], at[45]); MULADD(at[28], at[44]); MULADD(at[29], at[43]); MULADD(at[30], at[42]); MULADD(at[31], at[41]); + COMBA_STORE(C->dp[40]); + /* 41 */ + COMBA_FORWARD; + MULADD(at[10], at[63]); MULADD(at[11], at[62]); MULADD(at[12], at[61]); MULADD(at[13], at[60]); MULADD(at[14], at[59]); MULADD(at[15], at[58]); MULADD(at[16], at[57]); MULADD(at[17], at[56]); MULADD(at[18], at[55]); MULADD(at[19], at[54]); MULADD(at[20], at[53]); MULADD(at[21], at[52]); MULADD(at[22], at[51]); MULADD(at[23], at[50]); MULADD(at[24], at[49]); MULADD(at[25], at[48]); MULADD(at[26], at[47]); MULADD(at[27], at[46]); MULADD(at[28], at[45]); MULADD(at[29], at[44]); MULADD(at[30], at[43]); MULADD(at[31], at[42]); + COMBA_STORE(C->dp[41]); + /* 42 */ + COMBA_FORWARD; + MULADD(at[11], at[63]); MULADD(at[12], at[62]); MULADD(at[13], at[61]); MULADD(at[14], at[60]); MULADD(at[15], at[59]); MULADD(at[16], at[58]); MULADD(at[17], at[57]); MULADD(at[18], at[56]); MULADD(at[19], at[55]); MULADD(at[20], at[54]); MULADD(at[21], at[53]); MULADD(at[22], at[52]); MULADD(at[23], at[51]); MULADD(at[24], at[50]); MULADD(at[25], at[49]); MULADD(at[26], at[48]); MULADD(at[27], at[47]); MULADD(at[28], at[46]); MULADD(at[29], at[45]); MULADD(at[30], at[44]); MULADD(at[31], at[43]); + COMBA_STORE(C->dp[42]); + /* 43 */ + COMBA_FORWARD; + MULADD(at[12], at[63]); MULADD(at[13], at[62]); MULADD(at[14], at[61]); MULADD(at[15], at[60]); MULADD(at[16], at[59]); MULADD(at[17], at[58]); MULADD(at[18], at[57]); MULADD(at[19], at[56]); MULADD(at[20], at[55]); MULADD(at[21], at[54]); MULADD(at[22], at[53]); MULADD(at[23], at[52]); MULADD(at[24], at[51]); MULADD(at[25], at[50]); MULADD(at[26], at[49]); MULADD(at[27], at[48]); MULADD(at[28], at[47]); MULADD(at[29], at[46]); MULADD(at[30], at[45]); MULADD(at[31], at[44]); + COMBA_STORE(C->dp[43]); + /* 44 */ + COMBA_FORWARD; + MULADD(at[13], at[63]); MULADD(at[14], at[62]); MULADD(at[15], at[61]); MULADD(at[16], at[60]); MULADD(at[17], at[59]); MULADD(at[18], at[58]); MULADD(at[19], at[57]); MULADD(at[20], at[56]); MULADD(at[21], at[55]); MULADD(at[22], at[54]); MULADD(at[23], at[53]); MULADD(at[24], at[52]); MULADD(at[25], at[51]); MULADD(at[26], at[50]); MULADD(at[27], at[49]); MULADD(at[28], at[48]); MULADD(at[29], at[47]); MULADD(at[30], at[46]); MULADD(at[31], at[45]); + COMBA_STORE(C->dp[44]); + /* 45 */ + COMBA_FORWARD; + MULADD(at[14], at[63]); MULADD(at[15], at[62]); MULADD(at[16], at[61]); MULADD(at[17], at[60]); MULADD(at[18], at[59]); MULADD(at[19], at[58]); MULADD(at[20], at[57]); MULADD(at[21], at[56]); MULADD(at[22], at[55]); MULADD(at[23], at[54]); MULADD(at[24], at[53]); MULADD(at[25], at[52]); MULADD(at[26], at[51]); MULADD(at[27], at[50]); MULADD(at[28], at[49]); MULADD(at[29], at[48]); MULADD(at[30], at[47]); MULADD(at[31], at[46]); + COMBA_STORE(C->dp[45]); + /* 46 */ + COMBA_FORWARD; + MULADD(at[15], at[63]); MULADD(at[16], at[62]); MULADD(at[17], at[61]); MULADD(at[18], at[60]); MULADD(at[19], at[59]); MULADD(at[20], at[58]); MULADD(at[21], at[57]); MULADD(at[22], at[56]); MULADD(at[23], at[55]); MULADD(at[24], at[54]); MULADD(at[25], at[53]); MULADD(at[26], at[52]); MULADD(at[27], at[51]); MULADD(at[28], at[50]); MULADD(at[29], at[49]); MULADD(at[30], at[48]); MULADD(at[31], at[47]); + COMBA_STORE(C->dp[46]); + /* 47 */ + COMBA_FORWARD; + MULADD(at[16], at[63]); MULADD(at[17], at[62]); MULADD(at[18], at[61]); MULADD(at[19], at[60]); MULADD(at[20], at[59]); MULADD(at[21], at[58]); MULADD(at[22], at[57]); MULADD(at[23], at[56]); MULADD(at[24], at[55]); MULADD(at[25], at[54]); MULADD(at[26], at[53]); MULADD(at[27], at[52]); MULADD(at[28], at[51]); MULADD(at[29], at[50]); MULADD(at[30], at[49]); MULADD(at[31], at[48]); + COMBA_STORE(C->dp[47]); + /* 48 */ + COMBA_FORWARD; + MULADD(at[17], at[63]); MULADD(at[18], at[62]); MULADD(at[19], at[61]); MULADD(at[20], at[60]); MULADD(at[21], at[59]); MULADD(at[22], at[58]); MULADD(at[23], at[57]); MULADD(at[24], at[56]); MULADD(at[25], at[55]); MULADD(at[26], at[54]); MULADD(at[27], at[53]); MULADD(at[28], at[52]); MULADD(at[29], at[51]); MULADD(at[30], at[50]); MULADD(at[31], at[49]); + COMBA_STORE(C->dp[48]); + /* 49 */ + COMBA_FORWARD; + MULADD(at[18], at[63]); MULADD(at[19], at[62]); MULADD(at[20], at[61]); MULADD(at[21], at[60]); MULADD(at[22], at[59]); MULADD(at[23], at[58]); MULADD(at[24], at[57]); MULADD(at[25], at[56]); MULADD(at[26], at[55]); MULADD(at[27], at[54]); MULADD(at[28], at[53]); MULADD(at[29], at[52]); MULADD(at[30], at[51]); MULADD(at[31], at[50]); + COMBA_STORE(C->dp[49]); + /* 50 */ + COMBA_FORWARD; + MULADD(at[19], at[63]); MULADD(at[20], at[62]); MULADD(at[21], at[61]); MULADD(at[22], at[60]); MULADD(at[23], at[59]); MULADD(at[24], at[58]); MULADD(at[25], at[57]); MULADD(at[26], at[56]); MULADD(at[27], at[55]); MULADD(at[28], at[54]); MULADD(at[29], at[53]); MULADD(at[30], at[52]); MULADD(at[31], at[51]); + COMBA_STORE(C->dp[50]); + /* 51 */ + COMBA_FORWARD; + MULADD(at[20], at[63]); MULADD(at[21], at[62]); MULADD(at[22], at[61]); MULADD(at[23], at[60]); MULADD(at[24], at[59]); MULADD(at[25], at[58]); MULADD(at[26], at[57]); MULADD(at[27], at[56]); MULADD(at[28], at[55]); MULADD(at[29], at[54]); MULADD(at[30], at[53]); MULADD(at[31], at[52]); + COMBA_STORE(C->dp[51]); + /* 52 */ + COMBA_FORWARD; + MULADD(at[21], at[63]); MULADD(at[22], at[62]); MULADD(at[23], at[61]); MULADD(at[24], at[60]); MULADD(at[25], at[59]); MULADD(at[26], at[58]); MULADD(at[27], at[57]); MULADD(at[28], at[56]); MULADD(at[29], at[55]); MULADD(at[30], at[54]); MULADD(at[31], at[53]); + COMBA_STORE(C->dp[52]); + /* 53 */ + COMBA_FORWARD; + MULADD(at[22], at[63]); MULADD(at[23], at[62]); MULADD(at[24], at[61]); MULADD(at[25], at[60]); MULADD(at[26], at[59]); MULADD(at[27], at[58]); MULADD(at[28], at[57]); MULADD(at[29], at[56]); MULADD(at[30], at[55]); MULADD(at[31], at[54]); + COMBA_STORE(C->dp[53]); + /* 54 */ + COMBA_FORWARD; + MULADD(at[23], at[63]); MULADD(at[24], at[62]); MULADD(at[25], at[61]); MULADD(at[26], at[60]); MULADD(at[27], at[59]); MULADD(at[28], at[58]); MULADD(at[29], at[57]); MULADD(at[30], at[56]); MULADD(at[31], at[55]); + COMBA_STORE(C->dp[54]); + /* 55 */ + COMBA_FORWARD; + MULADD(at[24], at[63]); MULADD(at[25], at[62]); MULADD(at[26], at[61]); MULADD(at[27], at[60]); MULADD(at[28], at[59]); MULADD(at[29], at[58]); MULADD(at[30], at[57]); MULADD(at[31], at[56]); + COMBA_STORE(C->dp[55]); + /* 56 */ + COMBA_FORWARD; + MULADD(at[25], at[63]); MULADD(at[26], at[62]); MULADD(at[27], at[61]); MULADD(at[28], at[60]); MULADD(at[29], at[59]); MULADD(at[30], at[58]); MULADD(at[31], at[57]); + COMBA_STORE(C->dp[56]); + /* 57 */ + COMBA_FORWARD; + MULADD(at[26], at[63]); MULADD(at[27], at[62]); MULADD(at[28], at[61]); MULADD(at[29], at[60]); MULADD(at[30], at[59]); MULADD(at[31], at[58]); + COMBA_STORE(C->dp[57]); + /* 58 */ + COMBA_FORWARD; + MULADD(at[27], at[63]); MULADD(at[28], at[62]); MULADD(at[29], at[61]); MULADD(at[30], at[60]); MULADD(at[31], at[59]); + COMBA_STORE(C->dp[58]); + /* 59 */ + COMBA_FORWARD; + MULADD(at[28], at[63]); MULADD(at[29], at[62]); MULADD(at[30], at[61]); MULADD(at[31], at[60]); + COMBA_STORE(C->dp[59]); + /* 60 */ + COMBA_FORWARD; + MULADD(at[29], at[63]); MULADD(at[30], at[62]); MULADD(at[31], at[61]); + COMBA_STORE(C->dp[60]); + /* 61 */ + COMBA_FORWARD; + MULADD(at[30], at[63]); MULADD(at[31], at[62]); + COMBA_STORE(C->dp[61]); + /* 62 */ + COMBA_FORWARD; + MULADD(at[31], at[63]); + COMBA_STORE(C->dp[62]); + COMBA_STORE2(C->dp[63]); + C->used = 64; + C->sign = A->sign ^ B->sign; + mp_clamp(C); + COMBA_FINI; +} + + + +void s_mp_sqr_comba_4(const mp_int *A, mp_int *B) +{ + mp_digit *a, b[8], c0, c1, c2, sc0, sc1, sc2; + /* get rid of some compiler warnings */ + sc0 = 0; sc1 = 0; sc2 = 0; + + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADD2(a[2], a[3]); + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + COMBA_STORE2(b[7]); + COMBA_FINI; + + B->used = 8; + B->sign = ZPOS; + memcpy(B->dp, b, 8 * sizeof(mp_digit)); + mp_clamp(B); +} + +void s_mp_sqr_comba_8(const mp_int *A, mp_int *B) +{ + mp_digit *a, b[16], c0, c1, c2, sc0, sc1, sc2; + /* get rid of some compiler warnings */ + sc0 = 0; sc1 = 0; sc2 = 0; + + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADD2(a[3], a[7]); SQRADD2(a[4], a[6]); SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADD2(a[4], a[7]); SQRADD2(a[5], a[6]); + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADD2(a[5], a[7]); SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADD2(a[6], a[7]); + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + COMBA_STORE2(b[15]); + COMBA_FINI; + + B->used = 16; + B->sign = ZPOS; + memcpy(B->dp, b, 16 * sizeof(mp_digit)); + mp_clamp(B); +} + +void s_mp_sqr_comba_16(const mp_int *A, mp_int *B) +{ + mp_digit *a, b[32], c0, c1, c2, sc0, sc1, sc2; + /* get rid of some compiler warnings */ + sc0 = 0; sc1 = 0; sc2 = 0; + + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADDSC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + + /* output 23 */ + CARRY_FORWARD; + SQRADDSC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; + COMBA_STORE(b[23]); + + /* output 24 */ + CARRY_FORWARD; + SQRADDSC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]); + COMBA_STORE(b[24]); + + /* output 25 */ + CARRY_FORWARD; + SQRADDSC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB; + COMBA_STORE(b[25]); + + /* output 26 */ + CARRY_FORWARD; + SQRADD2(a[11], a[15]); SQRADD2(a[12], a[14]); SQRADD(a[13], a[13]); + COMBA_STORE(b[26]); + + /* output 27 */ + CARRY_FORWARD; + SQRADD2(a[12], a[15]); SQRADD2(a[13], a[14]); + COMBA_STORE(b[27]); + + /* output 28 */ + CARRY_FORWARD; + SQRADD2(a[13], a[15]); SQRADD(a[14], a[14]); + COMBA_STORE(b[28]); + + /* output 29 */ + CARRY_FORWARD; + SQRADD2(a[14], a[15]); + COMBA_STORE(b[29]); + + /* output 30 */ + CARRY_FORWARD; + SQRADD(a[15], a[15]); + COMBA_STORE(b[30]); + COMBA_STORE2(b[31]); + COMBA_FINI; + + B->used = 32; + B->sign = ZPOS; + memcpy(B->dp, b, 32 * sizeof(mp_digit)); + mp_clamp(B); +} + + +void s_mp_sqr_comba_32(const mp_int *A, mp_int *B) +{ + mp_digit *a, b[64], c0, c1, c2, sc0, sc1, sc2; + /* get rid of some compiler warnings */ + sc0 = 0; sc1 = 0; sc2 = 0; + + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[20]); SQRADDAC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[21]); SQRADDAC(a[1], a[20]); SQRADDAC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[22]); SQRADDAC(a[1], a[21]); SQRADDAC(a[2], a[20]); SQRADDAC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + + /* output 23 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[23]); SQRADDAC(a[1], a[22]); SQRADDAC(a[2], a[21]); SQRADDAC(a[3], a[20]); SQRADDAC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; + COMBA_STORE(b[23]); + + /* output 24 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[24]); SQRADDAC(a[1], a[23]); SQRADDAC(a[2], a[22]); SQRADDAC(a[3], a[21]); SQRADDAC(a[4], a[20]); SQRADDAC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]); + COMBA_STORE(b[24]); + + /* output 25 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[25]); SQRADDAC(a[1], a[24]); SQRADDAC(a[2], a[23]); SQRADDAC(a[3], a[22]); SQRADDAC(a[4], a[21]); SQRADDAC(a[5], a[20]); SQRADDAC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB; + COMBA_STORE(b[25]); + + /* output 26 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[26]); SQRADDAC(a[1], a[25]); SQRADDAC(a[2], a[24]); SQRADDAC(a[3], a[23]); SQRADDAC(a[4], a[22]); SQRADDAC(a[5], a[21]); SQRADDAC(a[6], a[20]); SQRADDAC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]); + COMBA_STORE(b[26]); + + /* output 27 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[27]); SQRADDAC(a[1], a[26]); SQRADDAC(a[2], a[25]); SQRADDAC(a[3], a[24]); SQRADDAC(a[4], a[23]); SQRADDAC(a[5], a[22]); SQRADDAC(a[6], a[21]); SQRADDAC(a[7], a[20]); SQRADDAC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB; + COMBA_STORE(b[27]); + + /* output 28 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[28]); SQRADDAC(a[1], a[27]); SQRADDAC(a[2], a[26]); SQRADDAC(a[3], a[25]); SQRADDAC(a[4], a[24]); SQRADDAC(a[5], a[23]); SQRADDAC(a[6], a[22]); SQRADDAC(a[7], a[21]); SQRADDAC(a[8], a[20]); SQRADDAC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]); + COMBA_STORE(b[28]); + + /* output 29 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[29]); SQRADDAC(a[1], a[28]); SQRADDAC(a[2], a[27]); SQRADDAC(a[3], a[26]); SQRADDAC(a[4], a[25]); SQRADDAC(a[5], a[24]); SQRADDAC(a[6], a[23]); SQRADDAC(a[7], a[22]); SQRADDAC(a[8], a[21]); SQRADDAC(a[9], a[20]); SQRADDAC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB; + COMBA_STORE(b[29]); + + /* output 30 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[30]); SQRADDAC(a[1], a[29]); SQRADDAC(a[2], a[28]); SQRADDAC(a[3], a[27]); SQRADDAC(a[4], a[26]); SQRADDAC(a[5], a[25]); SQRADDAC(a[6], a[24]); SQRADDAC(a[7], a[23]); SQRADDAC(a[8], a[22]); SQRADDAC(a[9], a[21]); SQRADDAC(a[10], a[20]); SQRADDAC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]); + COMBA_STORE(b[30]); + + /* output 31 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[31]); SQRADDAC(a[1], a[30]); SQRADDAC(a[2], a[29]); SQRADDAC(a[3], a[28]); SQRADDAC(a[4], a[27]); SQRADDAC(a[5], a[26]); SQRADDAC(a[6], a[25]); SQRADDAC(a[7], a[24]); SQRADDAC(a[8], a[23]); SQRADDAC(a[9], a[22]); SQRADDAC(a[10], a[21]); SQRADDAC(a[11], a[20]); SQRADDAC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB; + COMBA_STORE(b[31]); + + /* output 32 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[31]); SQRADDAC(a[2], a[30]); SQRADDAC(a[3], a[29]); SQRADDAC(a[4], a[28]); SQRADDAC(a[5], a[27]); SQRADDAC(a[6], a[26]); SQRADDAC(a[7], a[25]); SQRADDAC(a[8], a[24]); SQRADDAC(a[9], a[23]); SQRADDAC(a[10], a[22]); SQRADDAC(a[11], a[21]); SQRADDAC(a[12], a[20]); SQRADDAC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]); + COMBA_STORE(b[32]); + + /* output 33 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[31]); SQRADDAC(a[3], a[30]); SQRADDAC(a[4], a[29]); SQRADDAC(a[5], a[28]); SQRADDAC(a[6], a[27]); SQRADDAC(a[7], a[26]); SQRADDAC(a[8], a[25]); SQRADDAC(a[9], a[24]); SQRADDAC(a[10], a[23]); SQRADDAC(a[11], a[22]); SQRADDAC(a[12], a[21]); SQRADDAC(a[13], a[20]); SQRADDAC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB; + COMBA_STORE(b[33]); + + /* output 34 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[31]); SQRADDAC(a[4], a[30]); SQRADDAC(a[5], a[29]); SQRADDAC(a[6], a[28]); SQRADDAC(a[7], a[27]); SQRADDAC(a[8], a[26]); SQRADDAC(a[9], a[25]); SQRADDAC(a[10], a[24]); SQRADDAC(a[11], a[23]); SQRADDAC(a[12], a[22]); SQRADDAC(a[13], a[21]); SQRADDAC(a[14], a[20]); SQRADDAC(a[15], a[19]); SQRADDAC(a[16], a[18]); SQRADDDB; SQRADD(a[17], a[17]); + COMBA_STORE(b[34]); + + /* output 35 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[31]); SQRADDAC(a[5], a[30]); SQRADDAC(a[6], a[29]); SQRADDAC(a[7], a[28]); SQRADDAC(a[8], a[27]); SQRADDAC(a[9], a[26]); SQRADDAC(a[10], a[25]); SQRADDAC(a[11], a[24]); SQRADDAC(a[12], a[23]); SQRADDAC(a[13], a[22]); SQRADDAC(a[14], a[21]); SQRADDAC(a[15], a[20]); SQRADDAC(a[16], a[19]); SQRADDAC(a[17], a[18]); SQRADDDB; + COMBA_STORE(b[35]); + + /* output 36 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[31]); SQRADDAC(a[6], a[30]); SQRADDAC(a[7], a[29]); SQRADDAC(a[8], a[28]); SQRADDAC(a[9], a[27]); SQRADDAC(a[10], a[26]); SQRADDAC(a[11], a[25]); SQRADDAC(a[12], a[24]); SQRADDAC(a[13], a[23]); SQRADDAC(a[14], a[22]); SQRADDAC(a[15], a[21]); SQRADDAC(a[16], a[20]); SQRADDAC(a[17], a[19]); SQRADDDB; SQRADD(a[18], a[18]); + COMBA_STORE(b[36]); + + /* output 37 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[31]); SQRADDAC(a[7], a[30]); SQRADDAC(a[8], a[29]); SQRADDAC(a[9], a[28]); SQRADDAC(a[10], a[27]); SQRADDAC(a[11], a[26]); SQRADDAC(a[12], a[25]); SQRADDAC(a[13], a[24]); SQRADDAC(a[14], a[23]); SQRADDAC(a[15], a[22]); SQRADDAC(a[16], a[21]); SQRADDAC(a[17], a[20]); SQRADDAC(a[18], a[19]); SQRADDDB; + COMBA_STORE(b[37]); + + /* output 38 */ + CARRY_FORWARD; + SQRADDSC(a[7], a[31]); SQRADDAC(a[8], a[30]); SQRADDAC(a[9], a[29]); SQRADDAC(a[10], a[28]); SQRADDAC(a[11], a[27]); SQRADDAC(a[12], a[26]); SQRADDAC(a[13], a[25]); SQRADDAC(a[14], a[24]); SQRADDAC(a[15], a[23]); SQRADDAC(a[16], a[22]); SQRADDAC(a[17], a[21]); SQRADDAC(a[18], a[20]); SQRADDDB; SQRADD(a[19], a[19]); + COMBA_STORE(b[38]); + + /* output 39 */ + CARRY_FORWARD; + SQRADDSC(a[8], a[31]); SQRADDAC(a[9], a[30]); SQRADDAC(a[10], a[29]); SQRADDAC(a[11], a[28]); SQRADDAC(a[12], a[27]); SQRADDAC(a[13], a[26]); SQRADDAC(a[14], a[25]); SQRADDAC(a[15], a[24]); SQRADDAC(a[16], a[23]); SQRADDAC(a[17], a[22]); SQRADDAC(a[18], a[21]); SQRADDAC(a[19], a[20]); SQRADDDB; + COMBA_STORE(b[39]); + + /* output 40 */ + CARRY_FORWARD; + SQRADDSC(a[9], a[31]); SQRADDAC(a[10], a[30]); SQRADDAC(a[11], a[29]); SQRADDAC(a[12], a[28]); SQRADDAC(a[13], a[27]); SQRADDAC(a[14], a[26]); SQRADDAC(a[15], a[25]); SQRADDAC(a[16], a[24]); SQRADDAC(a[17], a[23]); SQRADDAC(a[18], a[22]); SQRADDAC(a[19], a[21]); SQRADDDB; SQRADD(a[20], a[20]); + COMBA_STORE(b[40]); + + /* output 41 */ + CARRY_FORWARD; + SQRADDSC(a[10], a[31]); SQRADDAC(a[11], a[30]); SQRADDAC(a[12], a[29]); SQRADDAC(a[13], a[28]); SQRADDAC(a[14], a[27]); SQRADDAC(a[15], a[26]); SQRADDAC(a[16], a[25]); SQRADDAC(a[17], a[24]); SQRADDAC(a[18], a[23]); SQRADDAC(a[19], a[22]); SQRADDAC(a[20], a[21]); SQRADDDB; + COMBA_STORE(b[41]); + + /* output 42 */ + CARRY_FORWARD; + SQRADDSC(a[11], a[31]); SQRADDAC(a[12], a[30]); SQRADDAC(a[13], a[29]); SQRADDAC(a[14], a[28]); SQRADDAC(a[15], a[27]); SQRADDAC(a[16], a[26]); SQRADDAC(a[17], a[25]); SQRADDAC(a[18], a[24]); SQRADDAC(a[19], a[23]); SQRADDAC(a[20], a[22]); SQRADDDB; SQRADD(a[21], a[21]); + COMBA_STORE(b[42]); + + /* output 43 */ + CARRY_FORWARD; + SQRADDSC(a[12], a[31]); SQRADDAC(a[13], a[30]); SQRADDAC(a[14], a[29]); SQRADDAC(a[15], a[28]); SQRADDAC(a[16], a[27]); SQRADDAC(a[17], a[26]); SQRADDAC(a[18], a[25]); SQRADDAC(a[19], a[24]); SQRADDAC(a[20], a[23]); SQRADDAC(a[21], a[22]); SQRADDDB; + COMBA_STORE(b[43]); + + /* output 44 */ + CARRY_FORWARD; + SQRADDSC(a[13], a[31]); SQRADDAC(a[14], a[30]); SQRADDAC(a[15], a[29]); SQRADDAC(a[16], a[28]); SQRADDAC(a[17], a[27]); SQRADDAC(a[18], a[26]); SQRADDAC(a[19], a[25]); SQRADDAC(a[20], a[24]); SQRADDAC(a[21], a[23]); SQRADDDB; SQRADD(a[22], a[22]); + COMBA_STORE(b[44]); + + /* output 45 */ + CARRY_FORWARD; + SQRADDSC(a[14], a[31]); SQRADDAC(a[15], a[30]); SQRADDAC(a[16], a[29]); SQRADDAC(a[17], a[28]); SQRADDAC(a[18], a[27]); SQRADDAC(a[19], a[26]); SQRADDAC(a[20], a[25]); SQRADDAC(a[21], a[24]); SQRADDAC(a[22], a[23]); SQRADDDB; + COMBA_STORE(b[45]); + + /* output 46 */ + CARRY_FORWARD; + SQRADDSC(a[15], a[31]); SQRADDAC(a[16], a[30]); SQRADDAC(a[17], a[29]); SQRADDAC(a[18], a[28]); SQRADDAC(a[19], a[27]); SQRADDAC(a[20], a[26]); SQRADDAC(a[21], a[25]); SQRADDAC(a[22], a[24]); SQRADDDB; SQRADD(a[23], a[23]); + COMBA_STORE(b[46]); + + /* output 47 */ + CARRY_FORWARD; + SQRADDSC(a[16], a[31]); SQRADDAC(a[17], a[30]); SQRADDAC(a[18], a[29]); SQRADDAC(a[19], a[28]); SQRADDAC(a[20], a[27]); SQRADDAC(a[21], a[26]); SQRADDAC(a[22], a[25]); SQRADDAC(a[23], a[24]); SQRADDDB; + COMBA_STORE(b[47]); + + /* output 48 */ + CARRY_FORWARD; + SQRADDSC(a[17], a[31]); SQRADDAC(a[18], a[30]); SQRADDAC(a[19], a[29]); SQRADDAC(a[20], a[28]); SQRADDAC(a[21], a[27]); SQRADDAC(a[22], a[26]); SQRADDAC(a[23], a[25]); SQRADDDB; SQRADD(a[24], a[24]); + COMBA_STORE(b[48]); + + /* output 49 */ + CARRY_FORWARD; + SQRADDSC(a[18], a[31]); SQRADDAC(a[19], a[30]); SQRADDAC(a[20], a[29]); SQRADDAC(a[21], a[28]); SQRADDAC(a[22], a[27]); SQRADDAC(a[23], a[26]); SQRADDAC(a[24], a[25]); SQRADDDB; + COMBA_STORE(b[49]); + + /* output 50 */ + CARRY_FORWARD; + SQRADDSC(a[19], a[31]); SQRADDAC(a[20], a[30]); SQRADDAC(a[21], a[29]); SQRADDAC(a[22], a[28]); SQRADDAC(a[23], a[27]); SQRADDAC(a[24], a[26]); SQRADDDB; SQRADD(a[25], a[25]); + COMBA_STORE(b[50]); + + /* output 51 */ + CARRY_FORWARD; + SQRADDSC(a[20], a[31]); SQRADDAC(a[21], a[30]); SQRADDAC(a[22], a[29]); SQRADDAC(a[23], a[28]); SQRADDAC(a[24], a[27]); SQRADDAC(a[25], a[26]); SQRADDDB; + COMBA_STORE(b[51]); + + /* output 52 */ + CARRY_FORWARD; + SQRADDSC(a[21], a[31]); SQRADDAC(a[22], a[30]); SQRADDAC(a[23], a[29]); SQRADDAC(a[24], a[28]); SQRADDAC(a[25], a[27]); SQRADDDB; SQRADD(a[26], a[26]); + COMBA_STORE(b[52]); + + /* output 53 */ + CARRY_FORWARD; + SQRADDSC(a[22], a[31]); SQRADDAC(a[23], a[30]); SQRADDAC(a[24], a[29]); SQRADDAC(a[25], a[28]); SQRADDAC(a[26], a[27]); SQRADDDB; + COMBA_STORE(b[53]); + + /* output 54 */ + CARRY_FORWARD; + SQRADDSC(a[23], a[31]); SQRADDAC(a[24], a[30]); SQRADDAC(a[25], a[29]); SQRADDAC(a[26], a[28]); SQRADDDB; SQRADD(a[27], a[27]); + COMBA_STORE(b[54]); + + /* output 55 */ + CARRY_FORWARD; + SQRADDSC(a[24], a[31]); SQRADDAC(a[25], a[30]); SQRADDAC(a[26], a[29]); SQRADDAC(a[27], a[28]); SQRADDDB; + COMBA_STORE(b[55]); + + /* output 56 */ + CARRY_FORWARD; + SQRADDSC(a[25], a[31]); SQRADDAC(a[26], a[30]); SQRADDAC(a[27], a[29]); SQRADDDB; SQRADD(a[28], a[28]); + COMBA_STORE(b[56]); + + /* output 57 */ + CARRY_FORWARD; + SQRADDSC(a[26], a[31]); SQRADDAC(a[27], a[30]); SQRADDAC(a[28], a[29]); SQRADDDB; + COMBA_STORE(b[57]); + + /* output 58 */ + CARRY_FORWARD; + SQRADD2(a[27], a[31]); SQRADD2(a[28], a[30]); SQRADD(a[29], a[29]); + COMBA_STORE(b[58]); + + /* output 59 */ + CARRY_FORWARD; + SQRADD2(a[28], a[31]); SQRADD2(a[29], a[30]); + COMBA_STORE(b[59]); + + /* output 60 */ + CARRY_FORWARD; + SQRADD2(a[29], a[31]); SQRADD(a[30], a[30]); + COMBA_STORE(b[60]); + + /* output 61 */ + CARRY_FORWARD; + SQRADD2(a[30], a[31]); + COMBA_STORE(b[61]); + + /* output 62 */ + CARRY_FORWARD; + SQRADD(a[31], a[31]); + COMBA_STORE(b[62]); + COMBA_STORE2(b[63]); + COMBA_FINI; + + B->used = 64; + B->sign = ZPOS; + memcpy(B->dp, b, 64 * sizeof(mp_digit)); + mp_clamp(B); +} diff --git a/security/nss/lib/freebl/mpi/mp_comba_amd64_sun.s b/security/nss/lib/freebl/mpi/mp_comba_amd64_sun.s new file mode 100644 index 000000000..a5181df33 --- /dev/null +++ b/security/nss/lib/freebl/mpi/mp_comba_amd64_sun.s @@ -0,0 +1,16097 @@ +//* TomsFastMath, a fast ISO C bignum library. +/ * +/ * This project is meant to fill in where LibTomMath +/ * falls short. That is speed ;-) +/ * +/ * This project is public domain and free for all purposes. +/ * +/ * Tom St Denis, tomstdenis@iahu.ca +/ */ + +//* +/ * The source file from which this assembly was derived +/ * comes from TFM v0.03, which has the above license. +/ * This source was compiled with an unnamed compiler at +/ * the highest optimization level. Afterwards, the +/ * trailing .section was removed because it causes errors +/ * in the Studio 10 compiler on AMD 64. +/ */ + + .file "mp_comba.c" + .text + .align 16 +.globl s_mp_mul_comba_4 + .type s_mp_mul_comba_4, @function +s_mp_mul_comba_4: +.LFB2: + pushq %r12 +.LCFI0: + pushq %rbp +.LCFI1: + pushq %rbx +.LCFI2: + movq 16(%rdi), %r9 + movq %rdx, %rbx + movq 16(%rsi), %rdx + movq (%r9), %rax + movq %rax, -64(%rsp) + movq 8(%r9), %r8 + movq %r8, -56(%rsp) + movq 16(%r9), %rbp + movq %rbp, -48(%rsp) + movq 24(%r9), %r12 + movq %r12, -40(%rsp) + movq (%rdx), %rcx + movq %rcx, -32(%rsp) + movq 8(%rdx), %r10 + movq %r10, -24(%rsp) + movq 16(%rdx), %r11 + xorl %r10d, %r10d + movq %r10, %r8 + movq %r10, %r9 + movq %r10, %rbp + movq %r11, -16(%rsp) + movq 16(%rbx), %r11 + movq 24(%rdx), %rax + movq %rax, -8(%rsp) +/APP + movq -64(%rsp),%rax + mulq -32(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rbp + +/NO_APP + movq %r8, (%r11) + movq %rbp, %r8 + movq %r10, %rbp +/APP + movq -64(%rsp),%rax + mulq -24(%rsp) + addq %rax,%r9 + adcq %rdx,%r8 + adcq $0,%rbp + +/NO_APP + movq %rbp, %r12 +/APP + movq -56(%rsp),%rax + mulq -32(%rsp) + addq %rax,%r9 + adcq %rdx,%r8 + adcq $0,%r12 + +/NO_APP + movq %r9, 8(%r11) + movq %r12, %r9 + movq %r10, %r12 +/APP + movq -64(%rsp),%rax + mulq -16(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%r12 + +/NO_APP + movq %r12, %rcx +/APP + movq -56(%rsp),%rax + mulq -24(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq -48(%rsp),%rax + mulq -32(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 16(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -64(%rsp),%rax + mulq -8(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -56(%rsp),%rax + mulq -16(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -48(%rsp),%rax + mulq -24(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq -40(%rsp),%rax + mulq -32(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 24(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -56(%rsp),%rax + mulq -8(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -48(%rsp),%rax + mulq -16(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq -40(%rsp),%rax + mulq -24(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 32(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -48(%rsp),%rax + mulq -8(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r8, %r12 + movq %r9, %rbp +/APP + movq -40(%rsp),%rax + mulq -16(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 40(%r11) + movq %rbp, %r8 + movq %r12, %rcx +/APP + movq -40(%rsp),%rax + mulq -8(%rsp) + addq %rax,%r8 + adcq %rdx,%rcx + adcq $0,%r10 + +/NO_APP + movq %r8, 48(%r11) + movl (%rsi), %esi + xorl (%rdi), %esi + testq %rcx, %rcx + movq %rcx, 56(%r11) + movl $8, 8(%rbx) + jne .L9 + .align 16 +.L18: + movl 8(%rbx), %edx + leal -1(%rdx), %edi + testl %edi, %edi + movl %edi, 8(%rbx) + je .L9 + leal -2(%rdx), %r10d + cmpq $0, (%r11,%r10,8) + je .L18 +.L9: + movl 8(%rbx), %edx + xorl %r11d, %r11d + testl %edx, %edx + cmovne %esi, %r11d + movl %r11d, (%rbx) + popq %rbx + popq %rbp + popq %r12 + ret +.LFE2: + .size s_mp_mul_comba_4, .-s_mp_mul_comba_4 + .align 16 +.globl s_mp_mul_comba_8 + .type s_mp_mul_comba_8, @function +s_mp_mul_comba_8: +.LFB3: + pushq %r12 +.LCFI3: + pushq %rbp +.LCFI4: + pushq %rbx +.LCFI5: + movq %rdx, %rbx + subq $8, %rsp +.LCFI6: + movq 16(%rdi), %rdx + movq (%rdx), %r8 + movq %r8, -120(%rsp) + movq 8(%rdx), %rbp + movq %rbp, -112(%rsp) + movq 16(%rdx), %r9 + movq %r9, -104(%rsp) + movq 24(%rdx), %r12 + movq %r12, -96(%rsp) + movq 32(%rdx), %rcx + movq %rcx, -88(%rsp) + movq 40(%rdx), %r10 + movq %r10, -80(%rsp) + movq 48(%rdx), %r11 + movq %r11, -72(%rsp) + movq 56(%rdx), %rax + movq 16(%rsi), %rdx + movq %rax, -64(%rsp) + movq (%rdx), %r8 + movq %r8, -56(%rsp) + movq 8(%rdx), %rbp + movq %rbp, -48(%rsp) + movq 16(%rdx), %r9 + movq %r9, -40(%rsp) + movq 24(%rdx), %r12 + movq %r12, -32(%rsp) + movq 32(%rdx), %rcx + movq %rcx, -24(%rsp) + movq 40(%rdx), %r10 + movq %r10, -16(%rsp) + movq 48(%rdx), %r11 + xorl %r10d, %r10d + movq %r10, %r8 + movq %r10, %r9 + movq %r10, %rbp + movq %r11, -8(%rsp) + movq 16(%rbx), %r11 + movq 56(%rdx), %rax + movq %rax, (%rsp) +/APP + movq -120(%rsp),%rax + mulq -56(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rbp + +/NO_APP + movq %r8, (%r11) + movq %rbp, %r8 + movq %r10, %rbp +/APP + movq -120(%rsp),%rax + mulq -48(%rsp) + addq %rax,%r9 + adcq %rdx,%r8 + adcq $0,%rbp + +/NO_APP + movq %rbp, %r12 +/APP + movq -112(%rsp),%rax + mulq -56(%rsp) + addq %rax,%r9 + adcq %rdx,%r8 + adcq $0,%r12 + +/NO_APP + movq %r9, 8(%r11) + movq %r12, %r9 + movq %r10, %r12 +/APP + movq -120(%rsp),%rax + mulq -40(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%r12 + +/NO_APP + movq %r12, %rcx +/APP + movq -112(%rsp),%rax + mulq -48(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq -104(%rsp),%rax + mulq -56(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 16(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -120(%rsp),%rax + mulq -32(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -112(%rsp),%rax + mulq -40(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -104(%rsp),%rax + mulq -48(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq -96(%rsp),%rax + mulq -56(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 24(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -120(%rsp),%rax + mulq -24(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -112(%rsp),%rax + mulq -32(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -104(%rsp),%rax + mulq -40(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -96(%rsp),%rax + mulq -48(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq -88(%rsp),%rax + mulq -56(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 32(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -120(%rsp),%rax + mulq -16(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -112(%rsp),%rax + mulq -24(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -104(%rsp),%rax + mulq -32(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -96(%rsp),%rax + mulq -40(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -88(%rsp),%rax + mulq -48(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq -80(%rsp),%rax + mulq -56(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 40(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -120(%rsp),%rax + mulq -8(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -112(%rsp),%rax + mulq -16(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -104(%rsp),%rax + mulq -24(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -96(%rsp),%rax + mulq -32(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -88(%rsp),%rax + mulq -40(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -80(%rsp),%rax + mulq -48(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq -72(%rsp),%rax + mulq -56(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 48(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -120(%rsp),%rax + mulq (%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -112(%rsp),%rax + mulq -8(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -104(%rsp),%rax + mulq -16(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -96(%rsp),%rax + mulq -24(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -88(%rsp),%rax + mulq -32(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -80(%rsp),%rax + mulq -40(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -72(%rsp),%rax + mulq -48(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq -64(%rsp),%rax + mulq -56(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 56(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -112(%rsp),%rax + mulq (%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -104(%rsp),%rax + mulq -8(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -96(%rsp),%rax + mulq -16(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -88(%rsp),%rax + mulq -24(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -80(%rsp),%rax + mulq -32(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -72(%rsp),%rax + mulq -40(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq -64(%rsp),%rax + mulq -48(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 64(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -104(%rsp),%rax + mulq (%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -96(%rsp),%rax + mulq -8(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -88(%rsp),%rax + mulq -16(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -80(%rsp),%rax + mulq -24(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -72(%rsp),%rax + mulq -32(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq -64(%rsp),%rax + mulq -40(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 72(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -96(%rsp),%rax + mulq (%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -88(%rsp),%rax + mulq -8(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -80(%rsp),%rax + mulq -16(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -72(%rsp),%rax + mulq -24(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq -64(%rsp),%rax + mulq -32(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 80(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -88(%rsp),%rax + mulq (%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -80(%rsp),%rax + mulq -8(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -72(%rsp),%rax + mulq -16(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq -64(%rsp),%rax + mulq -24(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 88(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -80(%rsp),%rax + mulq (%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -72(%rsp),%rax + mulq -8(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq -64(%rsp),%rax + mulq -16(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 96(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -72(%rsp),%rax + mulq (%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r8, %r12 + movq %r9, %rbp +/APP + movq -64(%rsp),%rax + mulq -8(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 104(%r11) + movq %rbp, %r8 + movq %r12, %rcx +/APP + movq -64(%rsp),%rax + mulq (%rsp) + addq %rax,%r8 + adcq %rdx,%rcx + adcq $0,%r10 + +/NO_APP + movq %r8, 112(%r11) + movl (%rsi), %esi + xorl (%rdi), %esi + testq %rcx, %rcx + movq %rcx, 120(%r11) + movl $16, 8(%rbx) + jne .L35 + .align 16 +.L43: + movl 8(%rbx), %edx + leal -1(%rdx), %edi + testl %edi, %edi + movl %edi, 8(%rbx) + je .L35 + leal -2(%rdx), %eax + cmpq $0, (%r11,%rax,8) + je .L43 +.L35: + movl 8(%rbx), %r11d + xorl %edx, %edx + testl %r11d, %r11d + cmovne %esi, %edx + movl %edx, (%rbx) + addq $8, %rsp + popq %rbx + popq %rbp + popq %r12 + ret +.LFE3: + .size s_mp_mul_comba_8, .-s_mp_mul_comba_8 + .align 16 +.globl s_mp_mul_comba_16 + .type s_mp_mul_comba_16, @function +s_mp_mul_comba_16: +.LFB4: + pushq %r12 +.LCFI7: + pushq %rbp +.LCFI8: + pushq %rbx +.LCFI9: + movq %rdx, %rbx + subq $136, %rsp +.LCFI10: + movq 16(%rdi), %rax + movq (%rax), %r8 + movq %r8, -120(%rsp) + movq 8(%rax), %rbp + movq %rbp, -112(%rsp) + movq 16(%rax), %r9 + movq %r9, -104(%rsp) + movq 24(%rax), %r12 + movq %r12, -96(%rsp) + movq 32(%rax), %rcx + movq %rcx, -88(%rsp) + movq 40(%rax), %r10 + movq %r10, -80(%rsp) + movq 48(%rax), %rdx + movq %rdx, -72(%rsp) + movq 56(%rax), %r11 + movq %r11, -64(%rsp) + movq 64(%rax), %r8 + movq %r8, -56(%rsp) + movq 72(%rax), %rbp + movq %rbp, -48(%rsp) + movq 80(%rax), %r9 + movq %r9, -40(%rsp) + movq 88(%rax), %r12 + movq %r12, -32(%rsp) + movq 96(%rax), %rcx + movq %rcx, -24(%rsp) + movq 104(%rax), %r10 + movq %r10, -16(%rsp) + movq 112(%rax), %rdx + movq %rdx, -8(%rsp) + movq 120(%rax), %r11 + movq %r11, (%rsp) + movq 16(%rsi), %r11 + movq (%r11), %r8 + movq %r8, 8(%rsp) + movq 8(%r11), %rbp + movq %rbp, 16(%rsp) + movq 16(%r11), %r9 + movq %r9, 24(%rsp) + movq 24(%r11), %r12 + movq %r12, 32(%rsp) + movq 32(%r11), %rcx + movq %rcx, 40(%rsp) + movq 40(%r11), %r10 + movq %r10, 48(%rsp) + movq 48(%r11), %rdx + movq %rdx, 56(%rsp) + movq 56(%r11), %rax + movq %rax, 64(%rsp) + movq 64(%r11), %r8 + movq %r8, 72(%rsp) + movq 72(%r11), %rbp + movq %rbp, 80(%rsp) + movq 80(%r11), %r9 + movq %r9, 88(%rsp) + movq 88(%r11), %r12 + movq %r12, 96(%rsp) + movq 96(%r11), %rcx + movq %rcx, 104(%rsp) + movq 104(%r11), %r10 + movq %r10, 112(%rsp) + movq 112(%r11), %rdx + xorl %r10d, %r10d + movq %r10, %r8 + movq %r10, %r9 + movq %r10, %rbp + movq %rdx, 120(%rsp) + movq 120(%r11), %rax + movq %rax, 128(%rsp) + movq 16(%rbx), %r11 +/APP + movq -120(%rsp),%rax + mulq 8(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rbp + +/NO_APP + movq %r8, (%r11) + movq %rbp, %r8 + movq %r10, %rbp +/APP + movq -120(%rsp),%rax + mulq 16(%rsp) + addq %rax,%r9 + adcq %rdx,%r8 + adcq $0,%rbp + +/NO_APP + movq %rbp, %r12 +/APP + movq -112(%rsp),%rax + mulq 8(%rsp) + addq %rax,%r9 + adcq %rdx,%r8 + adcq $0,%r12 + +/NO_APP + movq %r9, 8(%r11) + movq %r12, %r9 + movq %r10, %r12 +/APP + movq -120(%rsp),%rax + mulq 24(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%r12 + +/NO_APP + movq %r12, %rcx +/APP + movq -112(%rsp),%rax + mulq 16(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq -104(%rsp),%rax + mulq 8(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 16(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -120(%rsp),%rax + mulq 32(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -112(%rsp),%rax + mulq 24(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -104(%rsp),%rax + mulq 16(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq -96(%rsp),%rax + mulq 8(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 24(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -120(%rsp),%rax + mulq 40(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -112(%rsp),%rax + mulq 32(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -104(%rsp),%rax + mulq 24(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -96(%rsp),%rax + mulq 16(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq -88(%rsp),%rax + mulq 8(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 32(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -120(%rsp),%rax + mulq 48(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -112(%rsp),%rax + mulq 40(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -104(%rsp),%rax + mulq 32(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -96(%rsp),%rax + mulq 24(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -88(%rsp),%rax + mulq 16(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq -80(%rsp),%rax + mulq 8(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 40(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -120(%rsp),%rax + mulq 56(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -112(%rsp),%rax + mulq 48(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -104(%rsp),%rax + mulq 40(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -96(%rsp),%rax + mulq 32(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -88(%rsp),%rax + mulq 24(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -80(%rsp),%rax + mulq 16(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq -72(%rsp),%rax + mulq 8(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 48(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -120(%rsp),%rax + mulq 64(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -112(%rsp),%rax + mulq 56(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -104(%rsp),%rax + mulq 48(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -96(%rsp),%rax + mulq 40(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -88(%rsp),%rax + mulq 32(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -80(%rsp),%rax + mulq 24(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -72(%rsp),%rax + mulq 16(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq -64(%rsp),%rax + mulq 8(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 56(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -120(%rsp),%rax + mulq 72(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -112(%rsp),%rax + mulq 64(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -104(%rsp),%rax + mulq 56(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -96(%rsp),%rax + mulq 48(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -88(%rsp),%rax + mulq 40(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -80(%rsp),%rax + mulq 32(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -72(%rsp),%rax + mulq 24(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -64(%rsp),%rax + mulq 16(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq -56(%rsp),%rax + mulq 8(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 64(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -120(%rsp),%rax + mulq 80(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -112(%rsp),%rax + mulq 72(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -104(%rsp),%rax + mulq 64(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -96(%rsp),%rax + mulq 56(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -88(%rsp),%rax + mulq 48(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -80(%rsp),%rax + mulq 40(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -72(%rsp),%rax + mulq 32(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -64(%rsp),%rax + mulq 24(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -56(%rsp),%rax + mulq 16(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq -48(%rsp),%rax + mulq 8(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 72(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -120(%rsp),%rax + mulq 88(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -112(%rsp),%rax + mulq 80(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -104(%rsp),%rax + mulq 72(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -96(%rsp),%rax + mulq 64(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -88(%rsp),%rax + mulq 56(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -80(%rsp),%rax + mulq 48(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -72(%rsp),%rax + mulq 40(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -64(%rsp),%rax + mulq 32(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -56(%rsp),%rax + mulq 24(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -48(%rsp),%rax + mulq 16(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq -40(%rsp),%rax + mulq 8(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 80(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -120(%rsp),%rax + mulq 96(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -112(%rsp),%rax + mulq 88(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -104(%rsp),%rax + mulq 80(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -96(%rsp),%rax + mulq 72(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -88(%rsp),%rax + mulq 64(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -80(%rsp),%rax + mulq 56(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -72(%rsp),%rax + mulq 48(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -64(%rsp),%rax + mulq 40(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -56(%rsp),%rax + mulq 32(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -48(%rsp),%rax + mulq 24(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -40(%rsp),%rax + mulq 16(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq -32(%rsp),%rax + mulq 8(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 88(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -120(%rsp),%rax + mulq 104(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -112(%rsp),%rax + mulq 96(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -104(%rsp),%rax + mulq 88(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -96(%rsp),%rax + mulq 80(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -88(%rsp),%rax + mulq 72(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -80(%rsp),%rax + mulq 64(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -72(%rsp),%rax + mulq 56(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -64(%rsp),%rax + mulq 48(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -56(%rsp),%rax + mulq 40(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -48(%rsp),%rax + mulq 32(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -40(%rsp),%rax + mulq 24(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -32(%rsp),%rax + mulq 16(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq -24(%rsp),%rax + mulq 8(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 96(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -120(%rsp),%rax + mulq 112(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -112(%rsp),%rax + mulq 104(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -104(%rsp),%rax + mulq 96(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -96(%rsp),%rax + mulq 88(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -88(%rsp),%rax + mulq 80(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -80(%rsp),%rax + mulq 72(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -72(%rsp),%rax + mulq 64(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -64(%rsp),%rax + mulq 56(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -56(%rsp),%rax + mulq 48(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -48(%rsp),%rax + mulq 40(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -40(%rsp),%rax + mulq 32(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -32(%rsp),%rax + mulq 24(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -24(%rsp),%rax + mulq 16(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq -16(%rsp),%rax + mulq 8(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 104(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -120(%rsp),%rax + mulq 120(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -112(%rsp),%rax + mulq 112(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -104(%rsp),%rax + mulq 104(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -96(%rsp),%rax + mulq 96(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -88(%rsp),%rax + mulq 88(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -80(%rsp),%rax + mulq 80(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -72(%rsp),%rax + mulq 72(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -64(%rsp),%rax + mulq 64(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -56(%rsp),%rax + mulq 56(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -48(%rsp),%rax + mulq 48(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -40(%rsp),%rax + mulq 40(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -32(%rsp),%rax + mulq 32(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -24(%rsp),%rax + mulq 24(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -16(%rsp),%rax + mulq 16(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq -8(%rsp),%rax + mulq 8(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 112(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -120(%rsp),%rax + mulq 128(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -112(%rsp),%rax + mulq 120(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -104(%rsp),%rax + mulq 112(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -96(%rsp),%rax + mulq 104(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -88(%rsp),%rax + mulq 96(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -80(%rsp),%rax + mulq 88(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -72(%rsp),%rax + mulq 80(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -64(%rsp),%rax + mulq 72(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -56(%rsp),%rax + mulq 64(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -48(%rsp),%rax + mulq 56(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -40(%rsp),%rax + mulq 48(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -32(%rsp),%rax + mulq 40(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -24(%rsp),%rax + mulq 32(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -16(%rsp),%rax + mulq 24(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -8(%rsp),%rax + mulq 16(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq (%rsp),%rax + mulq 8(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 120(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -112(%rsp),%rax + mulq 128(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -104(%rsp),%rax + mulq 120(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -96(%rsp),%rax + mulq 112(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -88(%rsp),%rax + mulq 104(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -80(%rsp),%rax + mulq 96(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -72(%rsp),%rax + mulq 88(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -64(%rsp),%rax + mulq 80(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -56(%rsp),%rax + mulq 72(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -48(%rsp),%rax + mulq 64(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -40(%rsp),%rax + mulq 56(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -32(%rsp),%rax + mulq 48(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -24(%rsp),%rax + mulq 40(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -16(%rsp),%rax + mulq 32(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -8(%rsp),%rax + mulq 24(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq (%rsp),%rax + mulq 16(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 128(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -104(%rsp),%rax + mulq 128(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -96(%rsp),%rax + mulq 120(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -88(%rsp),%rax + mulq 112(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -80(%rsp),%rax + mulq 104(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -72(%rsp),%rax + mulq 96(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -64(%rsp),%rax + mulq 88(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -56(%rsp),%rax + mulq 80(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -48(%rsp),%rax + mulq 72(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -40(%rsp),%rax + mulq 64(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -32(%rsp),%rax + mulq 56(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -24(%rsp),%rax + mulq 48(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -16(%rsp),%rax + mulq 40(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -8(%rsp),%rax + mulq 32(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq (%rsp),%rax + mulq 24(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 136(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -96(%rsp),%rax + mulq 128(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -88(%rsp),%rax + mulq 120(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -80(%rsp),%rax + mulq 112(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -72(%rsp),%rax + mulq 104(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -64(%rsp),%rax + mulq 96(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -56(%rsp),%rax + mulq 88(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -48(%rsp),%rax + mulq 80(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -40(%rsp),%rax + mulq 72(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -32(%rsp),%rax + mulq 64(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -24(%rsp),%rax + mulq 56(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -16(%rsp),%rax + mulq 48(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -8(%rsp),%rax + mulq 40(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq (%rsp),%rax + mulq 32(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 144(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -88(%rsp),%rax + mulq 128(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -80(%rsp),%rax + mulq 120(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -72(%rsp),%rax + mulq 112(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -64(%rsp),%rax + mulq 104(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -56(%rsp),%rax + mulq 96(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -48(%rsp),%rax + mulq 88(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -40(%rsp),%rax + mulq 80(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -32(%rsp),%rax + mulq 72(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -24(%rsp),%rax + mulq 64(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -16(%rsp),%rax + mulq 56(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -8(%rsp),%rax + mulq 48(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq (%rsp),%rax + mulq 40(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 152(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -80(%rsp),%rax + mulq 128(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -72(%rsp),%rax + mulq 120(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -64(%rsp),%rax + mulq 112(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -56(%rsp),%rax + mulq 104(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -48(%rsp),%rax + mulq 96(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -40(%rsp),%rax + mulq 88(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -32(%rsp),%rax + mulq 80(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -24(%rsp),%rax + mulq 72(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -16(%rsp),%rax + mulq 64(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -8(%rsp),%rax + mulq 56(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq (%rsp),%rax + mulq 48(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 160(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -72(%rsp),%rax + mulq 128(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -64(%rsp),%rax + mulq 120(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -56(%rsp),%rax + mulq 112(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -48(%rsp),%rax + mulq 104(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -40(%rsp),%rax + mulq 96(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -32(%rsp),%rax + mulq 88(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -24(%rsp),%rax + mulq 80(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -16(%rsp),%rax + mulq 72(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -8(%rsp),%rax + mulq 64(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq (%rsp),%rax + mulq 56(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 168(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -64(%rsp),%rax + mulq 128(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -56(%rsp),%rax + mulq 120(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -48(%rsp),%rax + mulq 112(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -40(%rsp),%rax + mulq 104(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -32(%rsp),%rax + mulq 96(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -24(%rsp),%rax + mulq 88(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -16(%rsp),%rax + mulq 80(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -8(%rsp),%rax + mulq 72(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq (%rsp),%rax + mulq 64(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 176(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -56(%rsp),%rax + mulq 128(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -48(%rsp),%rax + mulq 120(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -40(%rsp),%rax + mulq 112(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -32(%rsp),%rax + mulq 104(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -24(%rsp),%rax + mulq 96(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -16(%rsp),%rax + mulq 88(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -8(%rsp),%rax + mulq 80(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq (%rsp),%rax + mulq 72(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 184(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -48(%rsp),%rax + mulq 128(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -40(%rsp),%rax + mulq 120(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -32(%rsp),%rax + mulq 112(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -24(%rsp),%rax + mulq 104(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -16(%rsp),%rax + mulq 96(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -8(%rsp),%rax + mulq 88(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq (%rsp),%rax + mulq 80(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 192(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -40(%rsp),%rax + mulq 128(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -32(%rsp),%rax + mulq 120(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -24(%rsp),%rax + mulq 112(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -16(%rsp),%rax + mulq 104(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -8(%rsp),%rax + mulq 96(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq (%rsp),%rax + mulq 88(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 200(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -32(%rsp),%rax + mulq 128(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -24(%rsp),%rax + mulq 120(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -16(%rsp),%rax + mulq 112(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -8(%rsp),%rax + mulq 104(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq (%rsp),%rax + mulq 96(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 208(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -24(%rsp),%rax + mulq 128(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -16(%rsp),%rax + mulq 120(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + + movq -8(%rsp),%rax + mulq 112(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbp + movq %r8, %r12 +/APP + movq (%rsp),%rax + mulq 104(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 216(%r11) + movq %r12, %r9 + movq %rbp, %r8 + movq %r10, %rcx +/APP + movq -16(%rsp),%rax + mulq 128(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + + movq -8(%rsp),%rax + mulq 120(%rsp) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rcx + +/NO_APP + movq %r9, %rbp + movq %rcx, %r12 +/APP + movq (%rsp),%rax + mulq 112(%rsp) + addq %rax,%r8 + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %r8, 224(%r11) + movq %r12, %r9 + movq %rbp, %rcx + movq %r10, %r8 +/APP + movq -8(%rsp),%rax + mulq 128(%rsp) + addq %rax,%rcx + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r8, %r12 + movq %r9, %rbp +/APP + movq (%rsp),%rax + mulq 120(%rsp) + addq %rax,%rcx + adcq %rdx,%rbp + adcq $0,%r12 + +/NO_APP + movq %rcx, 232(%r11) + movq %rbp, %r8 + movq %r12, %rcx +/APP + movq (%rsp),%rax + mulq 128(%rsp) + addq %rax,%r8 + adcq %rdx,%rcx + adcq $0,%r10 + +/NO_APP + movq %r8, 240(%r11) + movl (%rsi), %esi + xorl (%rdi), %esi + testq %rcx, %rcx + movq %rcx, 248(%r11) + movl $32, 8(%rbx) + jne .L76 + .align 16 +.L84: + movl 8(%rbx), %edx + leal -1(%rdx), %edi + testl %edi, %edi + movl %edi, 8(%rbx) + je .L76 + leal -2(%rdx), %eax + cmpq $0, (%r11,%rax,8) + je .L84 +.L76: + movl 8(%rbx), %edx + xorl %r11d, %r11d + testl %edx, %edx + cmovne %esi, %r11d + movl %r11d, (%rbx) + addq $136, %rsp + popq %rbx + popq %rbp + popq %r12 + ret +.LFE4: + .size s_mp_mul_comba_16, .-s_mp_mul_comba_16 + .align 16 +.globl s_mp_mul_comba_32 + .type s_mp_mul_comba_32, @function +s_mp_mul_comba_32: +.LFB5: + pushq %rbp +.LCFI11: + movq %rsp, %rbp +.LCFI12: + pushq %r13 +.LCFI13: + movq %rdx, %r13 + movl $256, %edx + pushq %r12 +.LCFI14: + movq %rsi, %r12 + pushq %rbx +.LCFI15: + movq %rdi, %rbx + subq $520, %rsp +.LCFI16: + movq 16(%rdi), %rsi + leaq -544(%rbp), %rdi + call memcpy@PLT + movq 16(%r12), %rsi + leaq -288(%rbp), %rdi + movl $256, %edx + call memcpy@PLT + movq 16(%r13), %r9 + xorl %r8d, %r8d + movq %r8, %rsi + movq %r8, %rdi + movq %r8, %r10 +/APP + movq -544(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%r10 + +/NO_APP + movq %rsi, (%r9) + movq %r10, %rsi + movq %r8, %r10 +/APP + movq -544(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%r10 + +/NO_APP + movq %r10, %r11 +/APP + movq -536(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%r11 + +/NO_APP + movq %rdi, 8(%r9) + movq %r11, %rdi + movq %r8, %r11 +/APP + movq -544(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%r11 + +/NO_APP + movq %r11, %rcx +/APP + movq -536(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -528(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 16(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -544(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -536(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -528(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -520(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 24(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -544(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -536(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -528(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -520(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -512(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 32(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -544(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -536(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -528(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -520(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -512(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -504(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 40(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -544(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -536(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -528(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -520(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -512(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -504(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -496(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 48(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -544(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -536(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -528(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -520(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -512(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -504(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -496(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -488(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 56(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -544(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -536(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -528(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -520(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -512(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -504(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -496(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -488(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -480(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 64(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -544(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -536(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -528(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -520(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -512(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -504(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -496(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -488(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -480(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -472(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 72(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -544(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -536(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -528(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -520(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -512(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -504(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -496(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -488(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -480(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -472(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -464(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 80(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -544(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -536(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -528(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -520(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -512(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -504(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -496(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -488(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -480(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -472(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -464(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -456(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 88(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -544(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -536(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -528(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -520(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -512(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -504(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -496(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -488(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -480(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -472(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -464(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -456(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -448(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 96(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -544(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -536(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -528(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -520(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -512(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -504(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -496(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -488(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -480(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -472(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -464(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -456(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -448(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -440(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 104(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -544(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -536(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -528(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -520(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -512(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -504(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -496(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -488(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -480(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -472(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -464(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -456(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -448(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -440(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -432(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 112(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -544(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -536(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -528(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -520(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -512(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -504(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -496(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -488(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -480(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -472(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -464(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -456(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -448(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -440(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -432(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -424(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 120(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -544(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -536(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -528(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -520(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -512(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -504(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -496(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -488(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -480(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -472(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -464(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -456(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -448(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -440(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -432(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -424(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -416(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 128(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -544(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -536(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -528(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -520(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -512(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -504(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -496(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -488(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -480(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -472(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -464(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -456(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -448(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -440(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -432(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -424(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -416(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -408(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 136(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -544(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -536(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -528(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -520(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -512(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -504(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -496(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -488(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -480(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -472(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -464(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -456(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -448(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -440(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -432(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -424(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -416(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -408(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -400(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 144(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -544(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -536(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -528(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -520(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -512(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -504(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -496(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -488(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -480(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -472(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -464(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -456(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -448(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -440(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -432(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -424(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -416(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -408(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -400(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -392(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 152(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -544(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -536(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -528(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -520(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -512(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -504(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -496(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -488(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -480(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -472(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -464(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -456(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -448(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -440(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -432(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -424(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -416(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -408(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -400(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -392(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -384(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 160(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -544(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -536(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -528(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -520(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -512(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -504(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -496(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -488(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -480(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -472(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -464(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -456(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -448(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -440(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -432(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -424(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -416(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -408(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -400(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -392(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -384(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -376(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 168(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -544(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -536(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -528(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -520(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -512(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -504(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -496(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -488(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -480(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -472(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -464(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -456(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -448(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -440(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -432(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -424(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -416(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -408(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -400(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -392(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -384(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -376(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -368(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 176(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -544(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -536(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -528(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -520(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -512(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -504(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -496(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -488(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -480(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -472(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -464(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -456(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -448(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -440(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -432(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -424(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -416(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -408(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -400(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -392(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -384(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -376(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -368(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -360(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 184(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -544(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -536(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -528(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -520(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -512(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -504(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -496(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -488(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -480(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -472(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -464(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -456(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -448(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -440(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -432(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -424(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -416(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -408(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -400(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -392(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -384(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -376(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -368(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -360(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -352(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 192(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -544(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -536(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -528(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -520(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -512(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -504(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -496(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -488(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -480(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -472(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -464(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -456(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -448(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -440(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -432(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -424(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -416(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -408(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -400(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -392(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -384(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -376(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -368(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -360(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -352(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -344(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 200(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -544(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -536(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -528(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -520(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -512(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -504(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -496(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -488(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -480(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -472(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -464(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -456(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -448(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -440(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -432(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -424(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -416(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -408(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -400(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -392(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -384(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -376(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -368(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -360(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -352(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -344(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -336(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 208(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -544(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -536(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -528(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -520(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -512(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -504(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -496(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -488(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -480(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -472(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -464(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -456(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -448(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -440(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -432(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -424(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -416(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -408(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -400(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -392(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -384(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -376(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -368(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -360(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -352(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -344(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -336(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -328(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 216(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -544(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -536(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -528(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -520(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -512(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -504(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -496(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -488(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -480(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -472(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -464(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -456(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -448(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -440(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -432(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -424(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -416(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -408(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -400(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -392(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -384(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -376(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -368(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -360(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -352(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -344(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -336(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -328(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -320(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 224(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -544(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -536(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -528(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -520(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -512(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -504(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -496(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -488(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -480(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -472(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -464(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -456(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -448(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -440(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -432(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -424(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -416(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -408(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -400(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -392(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -384(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -376(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -368(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -360(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -352(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -344(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -336(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -328(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -320(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -312(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 232(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -544(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -536(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -528(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -520(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -512(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -504(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -496(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -488(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -480(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -472(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -464(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -456(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -448(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -440(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -432(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -424(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -416(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -408(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -400(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -392(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -384(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -376(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -368(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -360(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -352(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -344(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -336(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -328(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -320(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -312(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -304(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 240(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -544(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -536(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -528(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -520(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -512(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -504(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -496(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -488(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -480(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -472(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -464(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -456(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -448(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -440(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -432(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -424(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -416(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -408(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -400(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -392(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -384(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -376(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -368(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -360(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -352(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -344(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -336(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -328(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -320(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -312(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -304(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -296(%rbp),%rax + mulq -288(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 248(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -536(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -528(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -520(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -512(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -504(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -496(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -488(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -480(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -472(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -464(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -456(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -448(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -440(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -432(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -424(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -416(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -408(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -400(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -392(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -384(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -376(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -368(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -360(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -352(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -344(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -336(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -328(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -320(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -312(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -304(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -296(%rbp),%rax + mulq -280(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 256(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -528(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -520(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -512(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -504(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -496(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -488(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -480(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -472(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -464(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -456(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -448(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -440(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -432(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -424(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -416(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -408(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -400(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -392(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -384(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -376(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -368(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -360(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -352(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -344(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -336(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -328(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -320(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -312(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -304(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -296(%rbp),%rax + mulq -272(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 264(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -520(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -512(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -504(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -496(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -488(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -480(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -472(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -464(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -456(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -448(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -440(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -432(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -424(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -416(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -408(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -400(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -392(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -384(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -376(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -368(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -360(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -352(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -344(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -336(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -328(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -320(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -312(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -304(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -296(%rbp),%rax + mulq -264(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 272(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -512(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -504(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -496(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -488(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -480(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -472(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -464(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -456(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -448(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -440(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -432(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -424(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -416(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -408(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -400(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -392(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -384(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -376(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -368(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -360(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -352(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -344(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -336(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -328(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -320(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -312(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -304(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -296(%rbp),%rax + mulq -256(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 280(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -504(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -496(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -488(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -480(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -472(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -464(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -456(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -448(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -440(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -432(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -424(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -416(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -408(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -400(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -392(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -384(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -376(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -368(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -360(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -352(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -344(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -336(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -328(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -320(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -312(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -304(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -296(%rbp),%rax + mulq -248(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 288(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -496(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -488(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -480(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -472(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -464(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -456(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -448(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -440(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -432(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -424(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -416(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -408(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -400(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -392(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -384(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -376(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -368(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -360(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -352(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -344(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -336(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -328(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -320(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -312(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -304(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -296(%rbp),%rax + mulq -240(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 296(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -488(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -480(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -472(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -464(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -456(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -448(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -440(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -432(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -424(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -416(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -408(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -400(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -392(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -384(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -376(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -368(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -360(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -352(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -344(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -336(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -328(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -320(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -312(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -304(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -296(%rbp),%rax + mulq -232(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 304(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -480(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -472(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -464(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -456(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -448(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -440(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -432(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -424(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -416(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -408(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -400(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -392(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -384(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -376(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -368(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -360(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -352(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -344(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -336(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -328(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -320(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -312(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -304(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -296(%rbp),%rax + mulq -224(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 312(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -472(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -464(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -456(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -448(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -440(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -432(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -424(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -416(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -408(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -400(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -392(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -384(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -376(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -368(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -360(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -352(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -344(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -336(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -328(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -320(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -312(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -304(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -296(%rbp),%rax + mulq -216(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 320(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -464(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -456(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -448(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -440(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -432(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -424(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -416(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -408(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -400(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -392(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -384(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -376(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -368(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -360(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -352(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -344(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -336(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -328(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -320(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -312(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -304(%rbp),%rax + mulq -200(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -296(%rbp),%rax + mulq -208(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 328(%r9) + movq %r11, %rdi + movq %r10, %r11 + movq %r8, %r10 +/APP + movq -456(%rbp),%rax + mulq -40(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -448(%rbp),%rax + mulq -48(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -440(%rbp),%rax + mulq -56(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -432(%rbp),%rax + mulq -64(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -424(%rbp),%rax + mulq -72(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -416(%rbp),%rax + mulq -80(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -408(%rbp),%rax + mulq -88(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -400(%rbp),%rax + mulq -96(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -392(%rbp),%rax + mulq -104(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -384(%rbp),%rax + mulq -112(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -376(%rbp),%rax + mulq -120(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -368(%rbp),%rax + mulq -128(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -360(%rbp),%rax + mulq -136(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -352(%rbp),%rax + mulq -144(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -344(%rbp),%rax + mulq -152(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -336(%rbp),%rax + mulq -160(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -328(%rbp),%rax + mulq -168(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -320(%rbp),%rax + mulq -176(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -312(%rbp),%rax + mulq -184(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -304(%rbp),%rax + mulq -192(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + + movq -296(%rbp),%rax + mulq -200(%rbp) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%r10 + +/NO_APP + movq %r11, 336(%r9) + movq %r10, %rsi + movq %r8, %r10 +/APP + movq -448(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%r10 + +/NO_APP + movq %r10, %rcx +/APP + movq -440(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rcx + + movq -432(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rcx + + movq -424(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rcx + + movq -416(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rcx + + movq -408(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rcx + + movq -400(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rcx + + movq -392(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rcx + + movq -384(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rcx + + movq -376(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rcx + + movq -368(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rcx + + movq -360(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rcx + + movq -352(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rcx + + movq -344(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rcx + + movq -336(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rcx + + movq -328(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rcx + + movq -320(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rcx + + movq -312(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rcx + + movq -304(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rcx + +/NO_APP + movq %rsi, %r11 + movq %rcx, %r10 +/APP + movq -296(%rbp),%rax + mulq -192(%rbp) + addq %rax,%rdi + adcq %rdx,%r11 + adcq $0,%r10 + +/NO_APP + movq %rdi, 344(%r9) + movq %r11, %rcx + movq %r10, %rdi + movq %r8, %r11 +/APP + movq -440(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%r11 + +/NO_APP + movq %r11, %rsi +/APP + movq -432(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -424(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -416(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -408(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -400(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -392(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -384(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -376(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -368(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -360(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -352(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -344(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -336(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -328(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -320(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -312(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -304(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -296(%rbp),%rax + mulq -184(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 352(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -432(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -424(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -416(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -408(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -400(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -392(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -384(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -376(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -368(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -360(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -352(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -344(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -336(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -328(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -320(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -312(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -304(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -296(%rbp),%rax + mulq -176(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 360(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -424(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -416(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -408(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -400(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -392(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -384(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -376(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -368(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -360(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -352(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -344(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -336(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -328(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -320(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -312(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -304(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -296(%rbp),%rax + mulq -168(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 368(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -416(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -408(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -400(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -392(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -384(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -376(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -368(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -360(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -352(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -344(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -336(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -328(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -320(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -312(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -304(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -296(%rbp),%rax + mulq -160(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 376(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -408(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -400(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -392(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -384(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -376(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -368(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -360(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -352(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -344(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -336(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -328(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -320(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -312(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -304(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -296(%rbp),%rax + mulq -152(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 384(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -400(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -392(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -384(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -376(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -368(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -360(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -352(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -344(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -336(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -328(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -320(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -312(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -304(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -296(%rbp),%rax + mulq -144(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 392(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -392(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -384(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -376(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -368(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -360(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -352(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -344(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -336(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -328(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -320(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -312(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -304(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -296(%rbp),%rax + mulq -136(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 400(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -384(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -376(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -368(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -360(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -352(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -344(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -336(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -328(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -320(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -312(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -304(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -296(%rbp),%rax + mulq -128(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 408(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -376(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -368(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -360(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -352(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -344(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -336(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -328(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -320(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -312(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -304(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -296(%rbp),%rax + mulq -120(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 416(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -368(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -360(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -352(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -344(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -336(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -328(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -320(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -312(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -304(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -296(%rbp),%rax + mulq -112(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 424(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -360(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -352(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -344(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -336(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -328(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -320(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -312(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -304(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -296(%rbp),%rax + mulq -104(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 432(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -352(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -344(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -336(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -328(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -320(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -312(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -304(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -296(%rbp),%rax + mulq -96(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 440(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -344(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -336(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -328(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -320(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -312(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -304(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -296(%rbp),%rax + mulq -88(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 448(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -336(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -328(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -320(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -312(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -304(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -296(%rbp),%rax + mulq -80(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 456(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -328(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -320(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -312(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -304(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -296(%rbp),%rax + mulq -72(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 464(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -320(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -312(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + + movq -304(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rdi, %r10 + movq %rcx, %r11 +/APP + movq -296(%rbp),%rax + mulq -64(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 472(%r9) + movq %r11, %rdi + movq %r10, %rcx + movq %r8, %rsi +/APP + movq -312(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + + movq -304(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rcx + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r10 + movq %rsi, %r11 +/APP + movq -296(%rbp),%rax + mulq -56(%rbp) + addq %rax,%rcx + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rcx, 480(%r9) + movq %r11, %rdi + movq %r10, %rsi + movq %r8, %rcx +/APP + movq -304(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rsi + adcq %rdx,%rdi + adcq $0,%rcx + +/NO_APP + movq %rcx, %r11 + movq %rdi, %r10 +/APP + movq -296(%rbp),%rax + mulq -48(%rbp) + addq %rax,%rsi + adcq %rdx,%r10 + adcq $0,%r11 + +/NO_APP + movq %rsi, 488(%r9) + movq %r10, %rcx + movq %r11, %rsi +/APP + movq -296(%rbp),%rax + mulq -40(%rbp) + addq %rax,%rcx + adcq %rdx,%rsi + adcq $0,%r8 + +/NO_APP + movq %rcx, 496(%r9) + movl (%r12), %ecx + xorl (%rbx), %ecx + testq %rsi, %rsi + movq %rsi, 504(%r9) + movl $64, 8(%r13) + jne .L149 + .align 16 +.L157: + movl 8(%r13), %edx + leal -1(%rdx), %ebx + testl %ebx, %ebx + movl %ebx, 8(%r13) + je .L149 + leal -2(%rdx), %r12d + cmpq $0, (%r9,%r12,8) + je .L157 +.L149: + movl 8(%r13), %r9d + xorl %edx, %edx + testl %r9d, %r9d + cmovne %ecx, %edx + movl %edx, (%r13) + addq $520, %rsp + popq %rbx + popq %r12 + popq %r13 + leave + ret +.LFE5: + .size s_mp_mul_comba_32, .-s_mp_mul_comba_32 + .align 16 +.globl s_mp_sqr_comba_4 + .type s_mp_sqr_comba_4, @function +s_mp_sqr_comba_4: +.LFB6: + pushq %rbp +.LCFI17: + movq %rsi, %r11 + xorl %esi, %esi + movq %rsi, %r10 + movq %rsi, %rbp + movq %rsi, %r8 + pushq %rbx +.LCFI18: + movq %rsi, %rbx + movq 16(%rdi), %rcx + movq %rsi, %rdi +/APP + movq (%rcx),%rax + mulq %rax + addq %rax,%r10 + adcq %rdx,%rbx + adcq $0,%rdi + +/NO_APP + movq %r10, -72(%rsp) +/APP + movq (%rcx),%rax + mulq 8(%rcx) + addq %rax,%rbx + adcq %rdx,%rdi + adcq $0,%rbp + addq %rax,%rbx + adcq %rdx,%rdi + adcq $0,%rbp + +/NO_APP + movq %rbx, -64(%rsp) +/APP + movq (%rcx),%rax + mulq 16(%rcx) + addq %rax,%rdi + adcq %rdx,%rbp + adcq $0,%r8 + addq %rax,%rdi + adcq %rdx,%rbp + adcq $0,%r8 + +/NO_APP + movq %rbp, %rbx + movq %r8, %rbp +/APP + movq 8(%rcx),%rax + mulq %rax + addq %rax,%rdi + adcq %rdx,%rbx + adcq $0,%rbp + +/NO_APP + movq %rdi, -56(%rsp) + movq %rbp, %r9 + movq %rbx, %r8 + movq %rsi, %rdi +/APP + movq (%rcx),%rax + mulq 24(%rcx) + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rdi + addq %rax,%r8 + adcq %rdx,%r9 + adcq $0,%rdi + +/NO_APP + movq %r9, %rbx + movq %rdi, %rbp +/APP + movq 8(%rcx),%rax + mulq 16(%rcx) + addq %rax,%r8 + adcq %rdx,%rbx + adcq $0,%rbp + addq %rax,%r8 + adcq %rdx,%rbx + adcq $0,%rbp + +/NO_APP + movq %r8, -48(%rsp) + movq %rbp, %r9 + movq %rbx, %rdi + movq %rsi, %r8 + movl $8, 8(%r11) + movl $0, (%r11) +/APP + movq 8(%rcx),%rax + mulq 24(%rcx) + addq %rax,%rdi + adcq %rdx,%r9 + adcq $0,%r8 + addq %rax,%rdi + adcq %rdx,%r9 + adcq $0,%r8 + +/NO_APP + movq %r9, %rbx + movq %r8, %rbp +/APP + movq 16(%rcx),%rax + mulq %rax + addq %rax,%rdi + adcq %rdx,%rbx + adcq $0,%rbp + +/NO_APP + movq %rbp, %rax + movq %rdi, -40(%rsp) + movq %rbx, %rbp + movq %rax, %rdi + movq %rsi, %rbx +/APP + movq 16(%rcx),%rax + mulq 24(%rcx) + addq %rax,%rbp + adcq %rdx,%rdi + adcq $0,%rbx + addq %rax,%rbp + adcq %rdx,%rdi + adcq $0,%rbx + +/NO_APP + movq %rbp, -32(%rsp) + movq %rbx, %r9 +/APP + movq 24(%rcx),%rax + mulq %rax + addq %rax,%rdi + adcq %rdx,%r9 + adcq $0,%rsi + +/NO_APP + movq 16(%r11), %rdx + movq %rdi, -24(%rsp) + movq %r9, -16(%rsp) + movq %r10, (%rdx) + movq -64(%rsp), %r8 + movq %r8, 8(%rdx) + movq -56(%rsp), %rbp + movq %rbp, 16(%rdx) + movq -48(%rsp), %rdi + movq %rdi, 24(%rdx) + movq -40(%rsp), %rsi + movq %rsi, 32(%rdx) + movq -32(%rsp), %rbx + movq %rbx, 40(%rdx) + movq -24(%rsp), %rcx + movq %rcx, 48(%rdx) + movq -16(%rsp), %rax + movq %rax, 56(%rdx) + movl 8(%r11), %edx + testl %edx, %edx + je .L168 + leal -1(%rdx), %ecx + movq 16(%r11), %rsi + mov %ecx, %r10d + cmpq $0, (%rsi,%r10,8) + jne .L166 + movl %ecx, %edx + .align 16 +.L167: + testl %edx, %edx + movl %edx, %ecx + je .L171 + decl %edx + mov %edx, %eax + cmpq $0, (%rsi,%rax,8) + je .L167 + movl %ecx, 8(%r11) + movl %ecx, %edx +.L166: + testl %edx, %edx + je .L168 + popq %rbx + popq %rbp + movl (%r11), %eax + movl %eax, (%r11) + ret +.L171: + movl %edx, 8(%r11) + .align 16 +.L168: + popq %rbx + popq %rbp + xorl %eax, %eax + movl %eax, (%r11) + ret +.LFE6: + .size s_mp_sqr_comba_4, .-s_mp_sqr_comba_4 + .align 16 +.globl s_mp_sqr_comba_8 + .type s_mp_sqr_comba_8, @function +s_mp_sqr_comba_8: +.LFB7: + pushq %r14 +.LCFI19: + xorl %r9d, %r9d + movq %r9, %r14 + movq %r9, %r10 + pushq %r13 +.LCFI20: + movq %r9, %r13 + pushq %r12 +.LCFI21: + movq %r9, %r12 + pushq %rbp +.LCFI22: + movq %rsi, %rbp + movq %r9, %rsi + pushq %rbx +.LCFI23: + movq %r9, %rbx + subq $8, %rsp +.LCFI24: + movq 16(%rdi), %rcx +/APP + movq (%rcx),%rax + mulq %rax + addq %rax,%r14 + adcq %rdx,%rbx + adcq $0,%r12 + +/NO_APP + movq %r14, -120(%rsp) +/APP + movq (%rcx),%rax + mulq 8(%rcx) + addq %rax,%rbx + adcq %rdx,%r12 + adcq $0,%r10 + addq %rax,%rbx + adcq %rdx,%r12 + adcq $0,%r10 + +/NO_APP + movq %rbx, -112(%rsp) +/APP + movq (%rcx),%rax + mulq 16(%rcx) + addq %rax,%r12 + adcq %rdx,%r10 + adcq $0,%r13 + addq %rax,%r12 + adcq %rdx,%r10 + adcq $0,%r13 + +/NO_APP + movq %r10, %rbx + movq %r13, %r10 + movq %r9, %r13 +/APP + movq 8(%rcx),%rax + mulq %rax + addq %rax,%r12 + adcq %rdx,%rbx + adcq $0,%r10 + +/NO_APP + movq %r12, -104(%rsp) + movq %r10, %rdi + movq %rbx, %r11 +/APP + movq (%rcx),%rax + mulq 24(%rcx) + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%rsi + addq %rax,%r11 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %rbx + movq %rsi, %r10 + movq %r9, %rdi +/APP + movq 8(%rcx),%rax + mulq 16(%rcx) + addq %rax,%r11 + adcq %rdx,%rbx + adcq $0,%r10 + addq %rax,%r11 + adcq %rdx,%rbx + adcq $0,%r10 + +/NO_APP + movq %r9, %rsi + movq %r11, -96(%rsp) + movq %r10, %r8 + movq %rbx, %r12 + movq %r9, %r11 +/APP + movq (%rcx),%rax + mulq 32(%rcx) + addq %rax,%r12 + adcq %rdx,%r8 + adcq $0,%r13 + addq %rax,%r12 + adcq %rdx,%r8 + adcq $0,%r13 + + movq 8(%rcx),%rax + mulq 24(%rcx) + addq %rax,%r12 + adcq %rdx,%r8 + adcq $0,%r13 + addq %rax,%r12 + adcq %rdx,%r8 + adcq $0,%r13 + +/NO_APP + movq %r8, %rbx + movq %r13, %r10 + movq %r9, %r8 +/APP + movq 16(%rcx),%rax + mulq %rax + addq %rax,%r12 + adcq %rdx,%rbx + adcq $0,%r10 + +/NO_APP + movq %r12, -88(%rsp) +/APP + movq (%rcx),%rax + mulq 40(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 32(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 24(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + addq %r8,%rbx + adcq %rdi,%r10 + adcq %rsi,%r11 + addq %r8,%rbx + adcq %rdi,%r10 + adcq %rsi,%r11 + +/NO_APP + movq %rbx, -80(%rsp) +/APP + movq (%rcx),%rax + mulq 48(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 40(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 32(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r9, %rax + movq %rdi, %r13 + movq %rsi, %r12 +/APP + addq %r8,%r10 + adcq %r13,%r11 + adcq %r12,%rax + addq %r8,%r10 + adcq %r13,%r11 + adcq %r12,%rax + +/NO_APP + movq %rax, %rdx + movq %r11, %rbx + movq %r13, %rdi + movq %rdx, %r11 + movq %r12, %rsi +/APP + movq 24(%rcx),%rax + mulq %rax + addq %rax,%r10 + adcq %rdx,%rbx + adcq $0,%r11 + +/NO_APP + movq %r10, -72(%rsp) + movq %r11, %r10 +/APP + movq (%rcx),%rax + mulq 56(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 48(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 40(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 32(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r9, %rax +/APP + addq %r8,%rbx + adcq %rdi,%r10 + adcq %rsi,%rax + addq %r8,%rbx + adcq %rdi,%r10 + adcq %rsi,%rax + +/NO_APP + movq %rbx, -64(%rsp) + movq %rax, %r11 + movq %r9, %rbx +/APP + movq 8(%rcx),%rax + mulq 56(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 16(%rcx),%rax + mulq 48(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 40(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r13 + movq %rsi, %r12 +/APP + addq %r8,%r10 + adcq %r13,%r11 + adcq %r12,%rbx + addq %r8,%r10 + adcq %r13,%r11 + adcq %r12,%rbx + +/NO_APP + movq %rbx, %rsi + movq %r13, %rdi + movq %r11, %rbx + movq %r12, %r13 + movq %rsi, %r11 +/APP + movq 32(%rcx),%rax + mulq %rax + addq %rax,%r10 + adcq %rdx,%rbx + adcq $0,%r11 + +/NO_APP + movq %r10, -56(%rsp) + movq %r9, %r10 +/APP + movq 16(%rcx),%rax + mulq 56(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %r13,%r13 + + movq 24(%rcx),%rax + mulq 48(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%r13 + + movq 32(%rcx),%rax + mulq 40(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%r13 + +/NO_APP + movq %rdi, %r12 + movq %r13, %rax +/APP + addq %r8,%rbx + adcq %r12,%r11 + adcq %rax,%r10 + addq %r8,%rbx + adcq %r12,%r11 + adcq %rax,%r10 + +/NO_APP + movq %rbx, -48(%rsp) + movq %r11, %r12 + movq %r10, %rsi + movq %r9, %rbx + movq %r9, %r11 +/APP + movq 24(%rcx),%rax + mulq 56(%rcx) + addq %rax,%r12 + adcq %rdx,%rsi + adcq $0,%rbx + addq %rax,%r12 + adcq %rdx,%rsi + adcq $0,%rbx + +/NO_APP + movq %rbx, %r13 +/APP + movq 32(%rcx),%rax + mulq 48(%rcx) + addq %rax,%r12 + adcq %rdx,%rsi + adcq $0,%r13 + addq %rax,%r12 + adcq %rdx,%rsi + adcq $0,%r13 + +/NO_APP + movq %rsi, %r10 + movq %r13, %rbx + movq %r9, %r13 +/APP + movq 40(%rcx),%rax + mulq %rax + addq %rax,%r12 + adcq %rdx,%r10 + adcq $0,%rbx + +/NO_APP + movq %r12, -40(%rsp) + movq %rbx, %r8 + movq %r10, %rdi +/APP + movq 32(%rcx),%rax + mulq 56(%rcx) + addq %rax,%rdi + adcq %rdx,%r8 + adcq $0,%r11 + addq %rax,%rdi + adcq %rdx,%r8 + adcq $0,%r11 + +/NO_APP + movq %r8, %r10 + movq %r11, %rbx +/APP + movq 40(%rcx),%rax + mulq 48(%rcx) + addq %rax,%rdi + adcq %rdx,%r10 + adcq $0,%rbx + addq %rax,%rdi + adcq %rdx,%r10 + adcq $0,%rbx + +/NO_APP + movq %rdi, -32(%rsp) + movq %rbx, %rsi + movq %r10, %r12 +/APP + movq 40(%rcx),%rax + mulq 56(%rcx) + addq %rax,%r12 + adcq %rdx,%rsi + adcq $0,%r13 + addq %rax,%r12 + adcq %rdx,%rsi + adcq $0,%r13 + +/NO_APP + movq %rsi, %r10 + movq %r13, %rbx +/APP + movq 48(%rcx),%rax + mulq %rax + addq %rax,%r12 + adcq %rdx,%r10 + adcq $0,%rbx + +/NO_APP + movq %r12, -24(%rsp) + movq %r10, %rdi + movq %rbx, %rsi + movq %r9, %r10 + movl $16, 8(%rbp) + movl $0, (%rbp) +/APP + movq 48(%rcx),%rax + mulq 56(%rcx) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%r10 + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%r10 + +/NO_APP + movq %rdi, -16(%rsp) + movq %r10, %r8 +/APP + movq 56(%rcx),%rax + mulq %rax + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%r9 + +/NO_APP + movq 16(%rbp), %rax + movq %rsi, -8(%rsp) + movq %r8, (%rsp) + movq %r14, (%rax) + movq -112(%rsp), %rbx + movq %rbx, 8(%rax) + movq -104(%rsp), %rcx + movq %rcx, 16(%rax) + movq -96(%rsp), %rdx + movq %rdx, 24(%rax) + movq -88(%rsp), %r14 + movq %r14, 32(%rax) + movq -80(%rsp), %r13 + movq %r13, 40(%rax) + movq -72(%rsp), %r12 + movq %r12, 48(%rax) + movq -64(%rsp), %r11 + movq %r11, 56(%rax) + movq -56(%rsp), %r10 + movq %r10, 64(%rax) + movq -48(%rsp), %r9 + movq %r9, 72(%rax) + movq -40(%rsp), %r8 + movq %r8, 80(%rax) + movq -32(%rsp), %rdi + movq %rdi, 88(%rax) + movq -24(%rsp), %rsi + movq %rsi, 96(%rax) + movq -16(%rsp), %rbx + movq %rbx, 104(%rax) + movq -8(%rsp), %rcx + movq %rcx, 112(%rax) + movq (%rsp), %rdx + movq %rdx, 120(%rax) + movl 8(%rbp), %edx + testl %edx, %edx + je .L192 + leal -1(%rdx), %ecx + movq 16(%rbp), %rsi + mov %ecx, %r14d + cmpq $0, (%rsi,%r14,8) + jne .L190 + movl %ecx, %edx + .align 16 +.L191: + testl %edx, %edx + movl %edx, %ecx + je .L195 + decl %edx + mov %edx, %r9d + cmpq $0, (%rsi,%r9,8) + je .L191 + movl %ecx, 8(%rbp) + movl %ecx, %edx +.L190: + testl %edx, %edx + je .L192 + movl (%rbp), %eax + movl %eax, (%rbp) + addq $8, %rsp + popq %rbx + popq %rbp + popq %r12 + popq %r13 + popq %r14 + ret +.L195: + movl %edx, 8(%rbp) + .align 16 +.L192: + xorl %eax, %eax + movl %eax, (%rbp) + addq $8, %rsp + popq %rbx + popq %rbp + popq %r12 + popq %r13 + popq %r14 + ret +.LFE7: + .size s_mp_sqr_comba_8, .-s_mp_sqr_comba_8 + .align 16 +.globl s_mp_sqr_comba_16 + .type s_mp_sqr_comba_16, @function +s_mp_sqr_comba_16: +.LFB8: + pushq %rbp +.LCFI25: + xorl %r9d, %r9d + movq %r9, %r8 + movq %r9, %r11 + movq %rsp, %rbp +.LCFI26: + pushq %r14 +.LCFI27: + movq %rsi, %r14 + movq %r9, %rsi + pushq %r13 +.LCFI28: + movq %r9, %r13 + pushq %r12 +.LCFI29: + movq %r9, %r12 + pushq %rbx +.LCFI30: + movq %r9, %rbx + subq $256, %rsp +.LCFI31: + movq 16(%rdi), %rcx +/APP + movq (%rcx),%rax + mulq %rax + addq %rax,%r8 + adcq %rdx,%rbx + adcq $0,%rsi + +/NO_APP + movq %r8, -288(%rbp) +/APP + movq (%rcx),%rax + mulq 8(%rcx) + addq %rax,%rbx + adcq %rdx,%rsi + adcq $0,%r12 + addq %rax,%rbx + adcq %rdx,%rsi + adcq $0,%r12 + +/NO_APP + movq %rbx, -280(%rbp) +/APP + movq (%rcx),%rax + mulq 16(%rcx) + addq %rax,%rsi + adcq %rdx,%r12 + adcq $0,%r13 + addq %rax,%rsi + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r12, %rbx + movq %r13, %r10 +/APP + movq 8(%rcx),%rax + mulq %rax + addq %rax,%rsi + adcq %rdx,%rbx + adcq $0,%r10 + +/NO_APP + movq %rsi, -272(%rbp) + movq %r10, %rdi + movq %r9, %rsi + movq %rbx, %r10 +/APP + movq (%rcx),%rax + mulq 24(%rcx) + addq %rax,%r10 + adcq %rdx,%rdi + adcq $0,%r11 + addq %rax,%r10 + adcq %rdx,%rdi + adcq $0,%r11 + +/NO_APP + movq %rdi, %r12 + movq %r11, %rbx + movq %r9, %rdi +/APP + movq 8(%rcx),%rax + mulq 16(%rcx) + addq %rax,%r10 + adcq %rdx,%r12 + adcq $0,%rbx + addq %rax,%r10 + adcq %rdx,%r12 + adcq $0,%rbx + +/NO_APP + movq %r9, %r11 + movq %r10, -264(%rbp) + movq %rbx, %r8 + movq %r12, %r13 + movq %r9, %r12 +/APP + movq (%rcx),%rax + mulq 32(%rcx) + addq %rax,%r13 + adcq %rdx,%r8 + adcq $0,%r12 + addq %rax,%r13 + adcq %rdx,%r8 + adcq $0,%r12 + + movq 8(%rcx),%rax + mulq 24(%rcx) + addq %rax,%r13 + adcq %rdx,%r8 + adcq $0,%r12 + addq %rax,%r13 + adcq %rdx,%r8 + adcq $0,%r12 + +/NO_APP + movq %r8, %rbx + movq %r12, %r10 + movq %r9, %r8 +/APP + movq 16(%rcx),%rax + mulq %rax + addq %rax,%r13 + adcq %rdx,%rbx + adcq $0,%r10 + +/NO_APP + movq %r13, -256(%rbp) +/APP + movq (%rcx),%rax + mulq 40(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 32(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 24(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + addq %r8,%rbx + adcq %rdi,%r10 + adcq %rsi,%r11 + addq %r8,%rbx + adcq %rdi,%r10 + adcq %rsi,%r11 + +/NO_APP + movq %rbx, -248(%rbp) +/APP + movq (%rcx),%rax + mulq 48(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 40(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 32(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r9, %rax + movq %rdi, %r13 + movq %rsi, %r12 +/APP + addq %r8,%r10 + adcq %r13,%r11 + adcq %r12,%rax + addq %r8,%r10 + adcq %r13,%r11 + adcq %r12,%rax + +/NO_APP + movq %rax, %rdx + movq %r11, %rbx + movq %r13, %rdi + movq %rdx, %r11 + movq %r12, %rsi +/APP + movq 24(%rcx),%rax + mulq %rax + addq %rax,%r10 + adcq %rdx,%rbx + adcq $0,%r11 + +/NO_APP + movq %r10, -240(%rbp) + movq %r11, %r10 +/APP + movq (%rcx),%rax + mulq 56(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 48(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 40(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 32(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r9, %rdx +/APP + addq %r8,%rbx + adcq %rdi,%r10 + adcq %rsi,%rdx + addq %r8,%rbx + adcq %rdi,%r10 + adcq %rsi,%rdx + +/NO_APP + movq %rdx, %r11 + movq %rbx, -232(%rbp) + movq %r9, %rbx +/APP + movq (%rcx),%rax + mulq 64(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 56(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 48(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 40(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r13 + movq %rsi, %r12 +/APP + addq %r8,%r10 + adcq %r13,%r11 + adcq %r12,%rbx + addq %r8,%r10 + adcq %r13,%r11 + adcq %r12,%rbx + + movq 32(%rcx),%rax + mulq %rax + addq %rax,%r10 + adcq %rdx,%r11 + adcq $0,%rbx + +/NO_APP + movq %r13, %rdi + movq %r10, -224(%rbp) + movq %r12, %rsi + movq %rbx, %r10 + movq %r9, %r12 +/APP + movq (%rcx),%rax + mulq 72(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 64(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 56(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 48(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 40(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + addq %r8,%r11 + adcq %rdi,%r10 + adcq %rsi,%r12 + addq %r8,%r11 + adcq %rdi,%r10 + adcq %rsi,%r12 + +/NO_APP + movq %r11, -216(%rbp) + movq %r12, %rbx +/APP + movq (%rcx),%rax + mulq 80(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 72(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 64(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 56(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 48(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r9, %rax + movq %rdi, %r13 + movq %rsi, %r12 +/APP + addq %r8,%r10 + adcq %r13,%rbx + adcq %r12,%rax + addq %r8,%r10 + adcq %r13,%rbx + adcq %r12,%rax + +/NO_APP + movq %rax, %rdx + movq %rbx, %r11 + movq %r13, %rdi + movq %rdx, %rbx + movq %r12, %rsi +/APP + movq 40(%rcx),%rax + mulq %rax + addq %rax,%r10 + adcq %rdx,%r11 + adcq $0,%rbx + +/NO_APP + movq %r10, -208(%rbp) + movq %rbx, %r10 +/APP + movq (%rcx),%rax + mulq 88(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 80(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 72(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 64(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 56(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 40(%rcx),%rax + mulq 48(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r9, %rdx +/APP + addq %r8,%r11 + adcq %rdi,%r10 + adcq %rsi,%rdx + addq %r8,%r11 + adcq %rdi,%r10 + adcq %rsi,%rdx + +/NO_APP + movq %rdx, %r13 + movq %r11, -200(%rbp) + movq %r13, %r12 +/APP + movq (%rcx),%rax + mulq 96(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 88(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 80(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 72(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 64(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 40(%rcx),%rax + mulq 56(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r9, %rax + movq %rdi, %rdx + movq %rsi, %r11 +/APP + addq %r8,%r10 + adcq %rdx,%r12 + adcq %r11,%rax + addq %r8,%r10 + adcq %rdx,%r12 + adcq %r11,%rax + +/NO_APP + movq %rdx, %rbx + movq %rax, %r13 + movq %r11, %rsi +/APP + movq 48(%rcx),%rax + mulq %rax + addq %rax,%r10 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %rbx, %rdi + movq %r10, -192(%rbp) + movq %r13, %r10 +/APP + movq (%rcx),%rax + mulq 104(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + +/NO_APP + movq %r9, %r13 +/APP + movq 8(%rcx),%rax + mulq 96(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 88(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 80(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 72(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 40(%rcx),%rax + mulq 64(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 48(%rcx),%rax + mulq 56(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + addq %r8,%r12 + adcq %rdi,%r10 + adcq %rsi,%r13 + addq %r8,%r12 + adcq %rdi,%r10 + adcq %rsi,%r13 + +/NO_APP + movq %r12, -184(%rbp) + movq %r13, %r12 +/APP + movq (%rcx),%rax + mulq 112(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 104(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 96(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 88(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 80(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 40(%rcx),%rax + mulq 72(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 48(%rcx),%rax + mulq 64(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r9, %rax + movq %rdi, %rbx + movq %rsi, %rdx +/APP + addq %r8,%r10 + adcq %rbx,%r12 + adcq %rdx,%rax + addq %r8,%r10 + adcq %rbx,%r12 + adcq %rdx,%rax + +/NO_APP + movq %rdx, %r11 + movq %rax, %r13 + movq %rbx, %rdi +/APP + movq 56(%rcx),%rax + mulq %rax + addq %rax,%r10 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r11, %rsi + movq %r10, -176(%rbp) + movq %r13, %r10 +/APP + movq (%rcx),%rax + mulq 120(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + +/NO_APP + movq %r9, %r13 +/APP + movq 8(%rcx),%rax + mulq 112(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 104(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 96(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 88(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 40(%rcx),%rax + mulq 80(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 48(%rcx),%rax + mulq 72(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 56(%rcx),%rax + mulq 64(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + addq %r8,%r12 + adcq %rdi,%r10 + adcq %rsi,%r13 + addq %r8,%r12 + adcq %rdi,%r10 + adcq %rsi,%r13 + +/NO_APP + movq %r12, -168(%rbp) + movq %r13, %r12 +/APP + movq 8(%rcx),%rax + mulq 120(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 16(%rcx),%rax + mulq 112(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 104(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 96(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 40(%rcx),%rax + mulq 88(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 48(%rcx),%rax + mulq 80(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 56(%rcx),%rax + mulq 72(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r9, %rax + movq %rdi, %rbx + movq %rsi, %rdx +/APP + addq %r8,%r10 + adcq %rbx,%r12 + adcq %rdx,%rax + addq %r8,%r10 + adcq %rbx,%r12 + adcq %rdx,%rax + +/NO_APP + movq %rdx, %r11 + movq %rax, %r13 + movq %rbx, %rdi +/APP + movq 64(%rcx),%rax + mulq %rax + addq %rax,%r10 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r11, %rsi + movq %r10, -160(%rbp) + movq %r9, %r11 +/APP + movq 16(%rcx),%rax + mulq 120(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + +/NO_APP + movq %r13, %r10 + movq %r9, %rbx +/APP + movq 24(%rcx),%rax + mulq 112(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 104(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 40(%rcx),%rax + mulq 96(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 48(%rcx),%rax + mulq 88(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 56(%rcx),%rax + mulq 80(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 64(%rcx),%rax + mulq 72(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + addq %r8,%r12 + adcq %rdi,%r10 + adcq %rsi,%r11 + addq %r8,%r12 + adcq %rdi,%r10 + adcq %rsi,%r11 + +/NO_APP + movq %r12, -152(%rbp) +/APP + movq 24(%rcx),%rax + mulq 120(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 32(%rcx),%rax + mulq 112(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 40(%rcx),%rax + mulq 104(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 48(%rcx),%rax + mulq 96(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 56(%rcx),%rax + mulq 88(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 64(%rcx),%rax + mulq 80(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r13 + movq %rsi, %r12 +/APP + addq %r8,%r10 + adcq %r13,%r11 + adcq %r12,%rbx + addq %r8,%r10 + adcq %r13,%r11 + adcq %r12,%rbx + +/NO_APP + movq %rbx, %rdx + movq %r13, %rdi + movq %r11, %rbx + movq %r12, %rsi + movq %rdx, %r11 + movq %r9, %r12 +/APP + movq 72(%rcx),%rax + mulq %rax + addq %rax,%r10 + adcq %rdx,%rbx + adcq $0,%r11 + +/NO_APP + movq %r10, -144(%rbp) + movq %r11, %r10 +/APP + movq 32(%rcx),%rax + mulq 120(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 40(%rcx),%rax + mulq 112(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 48(%rcx),%rax + mulq 104(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 56(%rcx),%rax + mulq 96(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 64(%rcx),%rax + mulq 88(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 72(%rcx),%rax + mulq 80(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + addq %r8,%rbx + adcq %rdi,%r10 + adcq %rsi,%r12 + addq %r8,%rbx + adcq %rdi,%r10 + adcq %rsi,%r12 + +/NO_APP + movq %rbx, -136(%rbp) + movq %r12, %r11 +/APP + movq 40(%rcx),%rax + mulq 120(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 48(%rcx),%rax + mulq 112(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 56(%rcx),%rax + mulq 104(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 64(%rcx),%rax + mulq 96(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 72(%rcx),%rax + mulq 88(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r9, %rax + movq %rdi, %r13 + movq %rsi, %r12 +/APP + addq %r8,%r10 + adcq %r13,%r11 + adcq %r12,%rax + addq %r8,%r10 + adcq %r13,%r11 + adcq %r12,%rax + +/NO_APP + movq %rax, %rdx + movq %r11, %rbx + movq %r13, %rdi + movq %rdx, %r11 + movq %r12, %rsi +/APP + movq 80(%rcx),%rax + mulq %rax + addq %rax,%r10 + adcq %rdx,%rbx + adcq $0,%r11 + +/NO_APP + movq %r10, -128(%rbp) + movq %r11, %r10 +/APP + movq 48(%rcx),%rax + mulq 120(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 56(%rcx),%rax + mulq 112(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 64(%rcx),%rax + mulq 104(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 72(%rcx),%rax + mulq 96(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 80(%rcx),%rax + mulq 88(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r9, %rdx +/APP + addq %r8,%rbx + adcq %rdi,%r10 + adcq %rsi,%rdx + addq %r8,%rbx + adcq %rdi,%r10 + adcq %rsi,%rdx + +/NO_APP + movq %rbx, -120(%rbp) + movq %rdx, %r11 + movq %r9, %rbx +/APP + movq 56(%rcx),%rax + mulq 120(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 64(%rcx),%rax + mulq 112(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 72(%rcx),%rax + mulq 104(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 80(%rcx),%rax + mulq 96(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r13 + movq %rsi, %r12 +/APP + addq %r8,%r10 + adcq %r13,%r11 + adcq %r12,%rbx + addq %r8,%r10 + adcq %r13,%r11 + adcq %r12,%rbx + +/NO_APP + movq %rbx, %rdx + movq %r13, %rdi + movq %r11, %rbx + movq %r12, %rsi + movq %rdx, %r11 + movq %r9, %r12 +/APP + movq 88(%rcx),%rax + mulq %rax + addq %rax,%r10 + adcq %rdx,%rbx + adcq $0,%r11 + +/NO_APP + movq %r10, -112(%rbp) + movq %r11, %r10 +/APP + movq 64(%rcx),%rax + mulq 120(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 72(%rcx),%rax + mulq 112(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 80(%rcx),%rax + mulq 104(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 88(%rcx),%rax + mulq 96(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + addq %r8,%rbx + adcq %rdi,%r10 + adcq %rsi,%r12 + addq %r8,%rbx + adcq %rdi,%r10 + adcq %rsi,%r12 + +/NO_APP + movq %rbx, -104(%rbp) + movq %r12, %r11 +/APP + movq 72(%rcx),%rax + mulq 120(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 80(%rcx),%rax + mulq 112(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 88(%rcx),%rax + mulq 104(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r9, %rax + movq %rdi, %r13 + movq %rsi, %r12 +/APP + addq %r8,%r10 + adcq %r13,%r11 + adcq %r12,%rax + addq %r8,%r10 + adcq %r13,%r11 + adcq %r12,%rax + +/NO_APP + movq %rax, %rdx + movq %r11, %rbx + movq %r13, %rdi + movq %rdx, %r11 + movq %r12, %rsi +/APP + movq 96(%rcx),%rax + mulq %rax + addq %rax,%r10 + adcq %rdx,%rbx + adcq $0,%r11 + +/NO_APP + movq %r10, -96(%rbp) + movq %r9, %r10 +/APP + movq 80(%rcx),%rax + mulq 120(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 88(%rcx),%rax + mulq 112(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 96(%rcx),%rax + mulq 104(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r12 + movq %rsi, %rax + movq %r9, %rsi +/APP + addq %r8,%rbx + adcq %r12,%r11 + adcq %rax,%r10 + addq %r8,%rbx + adcq %r12,%r11 + adcq %rax,%r10 + +/NO_APP + movq %r9, %r12 + movq %rbx, -88(%rbp) + movq %r11, %r13 + movq %r10, %r11 +/APP + movq 88(%rcx),%rax + mulq 120(%rcx) + addq %rax,%r13 + adcq %rdx,%r11 + adcq $0,%r12 + addq %rax,%r13 + adcq %rdx,%r11 + adcq $0,%r12 + +/NO_APP + movq %r12, %rdi +/APP + movq 96(%rcx),%rax + mulq 112(%rcx) + addq %rax,%r13 + adcq %rdx,%r11 + adcq $0,%rdi + addq %rax,%r13 + adcq %rdx,%r11 + adcq $0,%rdi + +/NO_APP + movq %r11, %rbx + movq %rdi, %r10 + movq %r9, %r11 +/APP + movq 104(%rcx),%rax + mulq %rax + addq %rax,%r13 + adcq %rdx,%rbx + adcq $0,%r10 + +/NO_APP + movq %r13, -80(%rbp) + movq %r10, %r8 + movq %rbx, %r10 +/APP + movq 96(%rcx),%rax + mulq 120(%rcx) + addq %rax,%r10 + adcq %rdx,%r8 + adcq $0,%rsi + addq %rax,%r10 + adcq %rdx,%r8 + adcq $0,%rsi + +/NO_APP + movq %r8, %r12 + movq %rsi, %rbx +/APP + movq 104(%rcx),%rax + mulq 112(%rcx) + addq %rax,%r10 + adcq %rdx,%r12 + adcq $0,%rbx + addq %rax,%r10 + adcq %rdx,%r12 + adcq $0,%rbx + +/NO_APP + movq %r10, -72(%rbp) + movq %rbx, %r13 + movq %r12, %rbx +/APP + movq 104(%rcx),%rax + mulq 120(%rcx) + addq %rax,%rbx + adcq %rdx,%r13 + adcq $0,%r11 + addq %rax,%rbx + adcq %rdx,%r13 + adcq $0,%r11 + +/NO_APP + movq %r11, %r12 + movq %r13, %r10 +/APP + movq 112(%rcx),%rax + mulq %rax + addq %rax,%rbx + adcq %rdx,%r10 + adcq $0,%r12 + +/NO_APP + movq %rbx, -64(%rbp) + movq %r10, %rdi + movq %r9, %rbx + movq %r12, %rsi +/APP + movq 112(%rcx),%rax + mulq 120(%rcx) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rbx + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%rbx + +/NO_APP + movq %rdi, -56(%rbp) + movq %rbx, %r8 +/APP + movq 120(%rcx),%rax + mulq %rax + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%r9 + +/NO_APP + movq %rsi, -48(%rbp) + movq 16(%r14), %rdi + leaq -288(%rbp), %rsi + movl $256, %edx + movq %r8, -40(%rbp) + movl $32, 8(%r14) + movl $0, (%r14) + call memcpy@PLT + movl 8(%r14), %edx + testl %edx, %edx + je .L232 + leal -1(%rdx), %ecx + movq 16(%r14), %rsi + mov %ecx, %r9d + cmpq $0, (%rsi,%r9,8) + jne .L230 + movl %ecx, %edx + .align 16 +.L231: + testl %edx, %edx + movl %edx, %ecx + je .L235 + decl %edx + mov %edx, %eax + cmpq $0, (%rsi,%rax,8) + je .L231 + movl %ecx, 8(%r14) + movl %ecx, %edx +.L230: + testl %edx, %edx + je .L232 + movl (%r14), %eax + movl %eax, (%r14) + addq $256, %rsp + popq %rbx + popq %r12 + popq %r13 + popq %r14 + leave + ret +.L235: + movl %edx, 8(%r14) + .align 16 +.L232: + xorl %eax, %eax + movl %eax, (%r14) + addq $256, %rsp + popq %rbx + popq %r12 + popq %r13 + popq %r14 + leave + ret +.LFE8: + .size s_mp_sqr_comba_16, .-s_mp_sqr_comba_16 + .align 16 +.globl s_mp_sqr_comba_32 + .type s_mp_sqr_comba_32, @function +s_mp_sqr_comba_32: +.LFB9: + pushq %rbp +.LCFI32: + xorl %r10d, %r10d + movq %r10, %r8 + movq %r10, %r11 + movq %rsp, %rbp +.LCFI33: + pushq %r14 +.LCFI34: + movq %rsi, %r14 + movq %r10, %rsi + pushq %r13 +.LCFI35: + movq %r10, %r13 + pushq %r12 +.LCFI36: + movq %r10, %r12 + pushq %rbx +.LCFI37: + movq %r10, %rbx + subq $512, %rsp +.LCFI38: + movq 16(%rdi), %rcx +/APP + movq (%rcx),%rax + mulq %rax + addq %rax,%r8 + adcq %rdx,%rbx + adcq $0,%rsi + +/NO_APP + movq %r8, -544(%rbp) +/APP + movq (%rcx),%rax + mulq 8(%rcx) + addq %rax,%rbx + adcq %rdx,%rsi + adcq $0,%r12 + addq %rax,%rbx + adcq %rdx,%rsi + adcq $0,%r12 + +/NO_APP + movq %rbx, -536(%rbp) +/APP + movq (%rcx),%rax + mulq 16(%rcx) + addq %rax,%rsi + adcq %rdx,%r12 + adcq $0,%r13 + addq %rax,%rsi + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r12, %rbx + movq %r13, %r9 +/APP + movq 8(%rcx),%rax + mulq %rax + addq %rax,%rsi + adcq %rdx,%rbx + adcq $0,%r9 + +/NO_APP + movq %rsi, -528(%rbp) + movq %r9, %rdi + movq %r10, %rsi + movq %rbx, %r9 +/APP + movq (%rcx),%rax + mulq 24(%rcx) + addq %rax,%r9 + adcq %rdx,%rdi + adcq $0,%r11 + addq %rax,%r9 + adcq %rdx,%rdi + adcq $0,%r11 + +/NO_APP + movq %rdi, %r12 + movq %r11, %r13 + movq %r10, %rdi +/APP + movq 8(%rcx),%rax + mulq 16(%rcx) + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r10, %r11 + movq %r9, -520(%rbp) + movq %r13, %r8 + movq %r12, %r13 + movq %r10, %r12 +/APP + movq (%rcx),%rax + mulq 32(%rcx) + addq %rax,%r13 + adcq %rdx,%r8 + adcq $0,%r12 + addq %rax,%r13 + adcq %rdx,%r8 + adcq $0,%r12 + + movq 8(%rcx),%rax + mulq 24(%rcx) + addq %rax,%r13 + adcq %rdx,%r8 + adcq $0,%r12 + addq %rax,%r13 + adcq %rdx,%r8 + adcq $0,%r12 + +/NO_APP + movq %r8, %rbx + movq %r12, %r9 + movq %r10, %r8 +/APP + movq 16(%rcx),%rax + mulq %rax + addq %rax,%r13 + adcq %rdx,%rbx + adcq $0,%r9 + +/NO_APP + movq %r13, -512(%rbp) +/APP + movq (%rcx),%rax + mulq 40(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 32(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 24(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + addq %r8,%rbx + adcq %rdi,%r9 + adcq %rsi,%r11 + addq %r8,%rbx + adcq %rdi,%r9 + adcq %rsi,%r11 + +/NO_APP + movq %rbx, -504(%rbp) +/APP + movq (%rcx),%rax + mulq 48(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 40(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 32(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r10, %rax + movq %rdi, %r13 + movq %rsi, %r12 +/APP + addq %r8,%r9 + adcq %r13,%r11 + adcq %r12,%rax + addq %r8,%r9 + adcq %r13,%r11 + adcq %r12,%rax + +/NO_APP + movq %rax, %rdx + movq %r11, %rbx + movq %r13, %rdi + movq %rdx, %r11 + movq %r12, %rsi +/APP + movq 24(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%rbx + adcq $0,%r11 + +/NO_APP + movq %r9, -496(%rbp) + movq %r11, %r9 +/APP + movq (%rcx),%rax + mulq 56(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 48(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 40(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 32(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r10, %rdx +/APP + addq %r8,%rbx + adcq %rdi,%r9 + adcq %rsi,%rdx + addq %r8,%rbx + adcq %rdi,%r9 + adcq %rsi,%rdx + +/NO_APP + movq %rdx, %r11 + movq %rbx, -488(%rbp) + movq %r10, %rbx +/APP + movq (%rcx),%rax + mulq 64(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 56(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 48(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 40(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r13 + movq %rsi, %r12 +/APP + addq %r8,%r9 + adcq %r13,%r11 + adcq %r12,%rbx + addq %r8,%r9 + adcq %r13,%r11 + adcq %r12,%rbx + + movq 32(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r11 + adcq $0,%rbx + +/NO_APP + movq %r13, %rdi + movq %r9, -480(%rbp) + movq %r12, %rsi + movq %rbx, %r9 + movq %r10, %r12 +/APP + movq (%rcx),%rax + mulq 72(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 64(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 56(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 48(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 40(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + addq %r8,%r11 + adcq %rdi,%r9 + adcq %rsi,%r12 + addq %r8,%r11 + adcq %rdi,%r9 + adcq %rsi,%r12 + +/NO_APP + movq %r11, -472(%rbp) + movq %r12, %rbx +/APP + movq (%rcx),%rax + mulq 80(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 72(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 64(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 56(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 48(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r10, %rax + movq %rdi, %r13 + movq %rsi, %r12 +/APP + addq %r8,%r9 + adcq %r13,%rbx + adcq %r12,%rax + addq %r8,%r9 + adcq %r13,%rbx + adcq %r12,%rax + +/NO_APP + movq %rax, %rdx + movq %rbx, %r11 + movq %r13, %rdi + movq %rdx, %rbx + movq %r12, %rsi +/APP + movq 40(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r11 + adcq $0,%rbx + +/NO_APP + movq %r9, -464(%rbp) + movq %rbx, %r9 +/APP + movq (%rcx),%rax + mulq 88(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 80(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 72(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 64(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 56(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 40(%rcx),%rax + mulq 48(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r10, %rdx +/APP + addq %r8,%r11 + adcq %rdi,%r9 + adcq %rsi,%rdx + addq %r8,%r11 + adcq %rdi,%r9 + adcq %rsi,%rdx + +/NO_APP + movq %rdx, %r13 + movq %r11, -456(%rbp) + movq %r13, %r12 + movq %r10, %r13 +/APP + movq (%rcx),%rax + mulq 96(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 88(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 80(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 72(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 64(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 40(%rcx),%rax + mulq 56(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %rax + movq %rsi, %r11 +/APP + addq %r8,%r9 + adcq %rax,%r12 + adcq %r11,%r13 + addq %r8,%r9 + adcq %rax,%r12 + adcq %r11,%r13 + +/NO_APP + movq %rax, %rbx + movq %r11, %rsi +/APP + movq 48(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %rbx, %rdi + movq %r9, -448(%rbp) + movq %r13, %r9 +/APP + movq (%rcx),%rax + mulq 104(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + +/NO_APP + movq %r10, %r13 +/APP + movq 8(%rcx),%rax + mulq 96(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 88(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 80(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 72(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 40(%rcx),%rax + mulq 64(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 48(%rcx),%rax + mulq 56(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + addq %r8,%r12 + adcq %rdi,%r9 + adcq %rsi,%r13 + addq %r8,%r12 + adcq %rdi,%r9 + adcq %rsi,%r13 + +/NO_APP + movq %r12, -440(%rbp) + movq %r10, %r12 +/APP + movq (%rcx),%rax + mulq 112(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 104(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 96(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 88(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 80(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 40(%rcx),%rax + mulq 72(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 48(%rcx),%rax + mulq 64(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r13, %rdx + movq %rdi, %rbx + movq %rsi, %r13 +/APP + addq %r8,%r9 + adcq %rbx,%rdx + adcq %r13,%r12 + addq %r8,%r9 + adcq %rbx,%rdx + adcq %r13,%r12 + +/NO_APP + movq %r12, %rax + movq %r13, %r11 + movq %rdx, %r12 + movq %rax, %r13 + movq %rbx, %rdi + movq %r11, %rsi +/APP + movq 56(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r9, -432(%rbp) + movq %r13, %r9 + movq %r10, %r13 +/APP + movq (%rcx),%rax + mulq 120(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 8(%rcx),%rax + mulq 112(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 104(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 96(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 88(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 40(%rcx),%rax + mulq 80(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 48(%rcx),%rax + mulq 72(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 56(%rcx),%rax + mulq 64(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r8, %rax + movq %rdi, %rdx + movq %rsi, %rbx +/APP + addq %rax,%r12 + adcq %rdx,%r9 + adcq %rbx,%r13 + addq %rax,%r12 + adcq %rdx,%r9 + adcq %rbx,%r13 + +/NO_APP + movq %r12, -424(%rbp) + movq %rdx, %r8 + movq %rax, %rsi + movq %rbx, %rdi + movq %r13, %r12 + movq %r10, %r13 +/APP + movq (%rcx),%rax + mulq 128(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 8(%rcx),%rax + mulq 120(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 16(%rcx),%rax + mulq 112(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 24(%rcx),%rax + mulq 104(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 32(%rcx),%rax + mulq 96(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 40(%rcx),%rax + mulq 88(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 48(%rcx),%rax + mulq 80(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 56(%rcx),%rax + mulq 72(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + +/NO_APP + movq %rsi, %rax + movq %r8, %rbx + movq %rdi, %rdx +/APP + addq %rax,%r9 + adcq %rbx,%r12 + adcq %rdx,%r13 + addq %rax,%r9 + adcq %rbx,%r12 + adcq %rdx,%r13 + +/NO_APP + movq %rdx, %r11 + movq %rax, %r8 + movq %rbx, %rdi +/APP + movq 64(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r11, %rsi + movq %r9, -416(%rbp) + movq %r13, %r9 +/APP + movq (%rcx),%rax + mulq 136(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + +/NO_APP + movq %r10, %r13 +/APP + movq 8(%rcx),%rax + mulq 128(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 120(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 112(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 104(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 40(%rcx),%rax + mulq 96(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 48(%rcx),%rax + mulq 88(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 56(%rcx),%rax + mulq 80(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 64(%rcx),%rax + mulq 72(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r8, %rbx + movq %rdi, %rax + movq %rsi, %rdx +/APP + addq %rbx,%r12 + adcq %rax,%r9 + adcq %rdx,%r13 + addq %rbx,%r12 + adcq %rax,%r9 + adcq %rdx,%r13 + +/NO_APP + movq %r12, -408(%rbp) + movq %rdx, %rdi + movq %rax, %r8 + movq %rbx, %rsi + movq %r13, %r12 + movq %r10, %r13 +/APP + movq (%rcx),%rax + mulq 144(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 8(%rcx),%rax + mulq 136(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 16(%rcx),%rax + mulq 128(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 24(%rcx),%rax + mulq 120(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 32(%rcx),%rax + mulq 112(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 40(%rcx),%rax + mulq 104(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 48(%rcx),%rax + mulq 96(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 56(%rcx),%rax + mulq 88(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 64(%rcx),%rax + mulq 80(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + +/NO_APP + movq %rsi, %rax + movq %r8, %rbx + movq %rdi, %rdx +/APP + addq %rax,%r9 + adcq %rbx,%r12 + adcq %rdx,%r13 + addq %rax,%r9 + adcq %rbx,%r12 + adcq %rdx,%r13 + +/NO_APP + movq %rdx, %r11 + movq %rax, %r8 + movq %rbx, %rdi +/APP + movq 72(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r11, %rsi + movq %r9, -400(%rbp) + movq %r13, %r9 +/APP + movq (%rcx),%rax + mulq 152(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + +/NO_APP + movq %r10, %r13 +/APP + movq 8(%rcx),%rax + mulq 144(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 136(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 128(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 120(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 40(%rcx),%rax + mulq 112(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 48(%rcx),%rax + mulq 104(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 56(%rcx),%rax + mulq 96(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 64(%rcx),%rax + mulq 88(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 72(%rcx),%rax + mulq 80(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r8, %rbx + movq %rdi, %rax + movq %rsi, %rdx +/APP + addq %rbx,%r12 + adcq %rax,%r9 + adcq %rdx,%r13 + addq %rbx,%r12 + adcq %rax,%r9 + adcq %rdx,%r13 + +/NO_APP + movq %r12, -392(%rbp) + movq %rdx, %rdi + movq %rax, %r8 + movq %rbx, %rsi + movq %r13, %r12 + movq %r10, %r13 +/APP + movq (%rcx),%rax + mulq 160(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 8(%rcx),%rax + mulq 152(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 16(%rcx),%rax + mulq 144(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 24(%rcx),%rax + mulq 136(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 32(%rcx),%rax + mulq 128(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 40(%rcx),%rax + mulq 120(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 48(%rcx),%rax + mulq 112(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 56(%rcx),%rax + mulq 104(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 64(%rcx),%rax + mulq 96(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 72(%rcx),%rax + mulq 88(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + +/NO_APP + movq %rsi, %rax + movq %r8, %rbx + movq %rdi, %rdx +/APP + addq %rax,%r9 + adcq %rbx,%r12 + adcq %rdx,%r13 + addq %rax,%r9 + adcq %rbx,%r12 + adcq %rdx,%r13 + +/NO_APP + movq %rdx, %r11 + movq %rax, %r8 + movq %rbx, %rdi +/APP + movq 80(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r11, %rsi + movq %r9, -384(%rbp) + movq %r13, %r9 +/APP + movq (%rcx),%rax + mulq 168(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + +/NO_APP + movq %r10, %r13 +/APP + movq 8(%rcx),%rax + mulq 160(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 152(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 144(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 136(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 40(%rcx),%rax + mulq 128(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 48(%rcx),%rax + mulq 120(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 56(%rcx),%rax + mulq 112(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 64(%rcx),%rax + mulq 104(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 72(%rcx),%rax + mulq 96(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 80(%rcx),%rax + mulq 88(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r8, %rbx + movq %rdi, %rax + movq %rsi, %rdx +/APP + addq %rbx,%r12 + adcq %rax,%r9 + adcq %rdx,%r13 + addq %rbx,%r12 + adcq %rax,%r9 + adcq %rdx,%r13 + +/NO_APP + movq %r12, -376(%rbp) + movq %rdx, %rdi + movq %rax, %r8 + movq %rbx, %rsi + movq %r13, %r12 + movq %r10, %r13 +/APP + movq (%rcx),%rax + mulq 176(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 8(%rcx),%rax + mulq 168(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 16(%rcx),%rax + mulq 160(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 24(%rcx),%rax + mulq 152(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 32(%rcx),%rax + mulq 144(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 40(%rcx),%rax + mulq 136(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 48(%rcx),%rax + mulq 128(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 56(%rcx),%rax + mulq 120(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 64(%rcx),%rax + mulq 112(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 72(%rcx),%rax + mulq 104(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 80(%rcx),%rax + mulq 96(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + +/NO_APP + movq %rsi, %rax + movq %r8, %rbx + movq %rdi, %rdx +/APP + addq %rax,%r9 + adcq %rbx,%r12 + adcq %rdx,%r13 + addq %rax,%r9 + adcq %rbx,%r12 + adcq %rdx,%r13 + +/NO_APP + movq %rdx, %r11 + movq %rax, %r8 + movq %rbx, %rdi +/APP + movq 88(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r11, %rsi + movq %r9, -368(%rbp) + movq %r13, %r9 +/APP + movq (%rcx),%rax + mulq 184(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + +/NO_APP + movq %r10, %r13 +/APP + movq 8(%rcx),%rax + mulq 176(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 16(%rcx),%rax + mulq 168(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 24(%rcx),%rax + mulq 160(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 32(%rcx),%rax + mulq 152(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 40(%rcx),%rax + mulq 144(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 48(%rcx),%rax + mulq 136(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 56(%rcx),%rax + mulq 128(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 64(%rcx),%rax + mulq 120(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 72(%rcx),%rax + mulq 112(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 80(%rcx),%rax + mulq 104(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 88(%rcx),%rax + mulq 96(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r8, %rbx + movq %rdi, %rax + movq %rsi, %rdx +/APP + addq %rbx,%r12 + adcq %rax,%r9 + adcq %rdx,%r13 + addq %rbx,%r12 + adcq %rax,%r9 + adcq %rdx,%r13 + +/NO_APP + movq %rdx, %rdi + movq %r12, -360(%rbp) + movq %rax, %r8 + movq %rbx, %rsi + movq %r13, %r12 + movq %r10, %r13 +/APP + movq (%rcx),%rax + mulq 192(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 8(%rcx),%rax + mulq 184(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 16(%rcx),%rax + mulq 176(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 24(%rcx),%rax + mulq 168(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 32(%rcx),%rax + mulq 160(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 40(%rcx),%rax + mulq 152(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 48(%rcx),%rax + mulq 144(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 56(%rcx),%rax + mulq 136(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 64(%rcx),%rax + mulq 128(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 72(%rcx),%rax + mulq 120(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 80(%rcx),%rax + mulq 112(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 88(%rcx),%rax + mulq 104(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + +/NO_APP + movq %r8, %rbx + movq %rdi, %rax +/APP + addq %rsi,%r9 + adcq %rbx,%r12 + adcq %rax,%r13 + addq %rsi,%r9 + adcq %rbx,%r12 + adcq %rax,%r13 + +/NO_APP + movq %rax, %r11 + movq %rbx, %r8 +/APP + movq 96(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r11, %rdi + movq %r9, -352(%rbp) + movq %r13, %r9 +/APP + movq (%rcx),%rax + mulq 200(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + +/NO_APP + movq %r10, %r13 +/APP + movq 8(%rcx),%rax + mulq 192(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 16(%rcx),%rax + mulq 184(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 24(%rcx),%rax + mulq 176(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 32(%rcx),%rax + mulq 168(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 40(%rcx),%rax + mulq 160(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 48(%rcx),%rax + mulq 152(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 56(%rcx),%rax + mulq 144(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 64(%rcx),%rax + mulq 136(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 72(%rcx),%rax + mulq 128(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 80(%rcx),%rax + mulq 120(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 88(%rcx),%rax + mulq 112(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 96(%rcx),%rax + mulq 104(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + addq %rsi,%r12 + adcq %r8,%r9 + adcq %rdi,%r13 + addq %rsi,%r12 + adcq %r8,%r9 + adcq %rdi,%r13 + +/NO_APP + movq %r12, -344(%rbp) + movq %r10, %r12 +/APP + movq (%rcx),%rax + mulq 208(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 8(%rcx),%rax + mulq 200(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 16(%rcx),%rax + mulq 192(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 24(%rcx),%rax + mulq 184(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 32(%rcx),%rax + mulq 176(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 40(%rcx),%rax + mulq 168(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 48(%rcx),%rax + mulq 160(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 56(%rcx),%rax + mulq 152(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 64(%rcx),%rax + mulq 144(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 72(%rcx),%rax + mulq 136(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 80(%rcx),%rax + mulq 128(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 88(%rcx),%rax + mulq 120(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 96(%rcx),%rax + mulq 112(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + +/NO_APP + movq %r13, %rdx + movq %r8, %rbx + movq %rdi, %r13 +/APP + addq %rsi,%r9 + adcq %rbx,%rdx + adcq %r13,%r12 + addq %rsi,%r9 + adcq %rbx,%rdx + adcq %r13,%r12 + +/NO_APP + movq %r12, %rax + movq %r13, %r11 + movq %rdx, %r12 + movq %rax, %r13 + movq %rbx, %r8 + movq %r11, %rdi +/APP + movq 104(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r9, -336(%rbp) + movq %r13, %r9 + movq %r10, %r13 +/APP + movq (%rcx),%rax + mulq 216(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 8(%rcx),%rax + mulq 208(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 16(%rcx),%rax + mulq 200(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 24(%rcx),%rax + mulq 192(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 32(%rcx),%rax + mulq 184(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 40(%rcx),%rax + mulq 176(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 48(%rcx),%rax + mulq 168(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 56(%rcx),%rax + mulq 160(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 64(%rcx),%rax + mulq 152(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 72(%rcx),%rax + mulq 144(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 80(%rcx),%rax + mulq 136(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 88(%rcx),%rax + mulq 128(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 96(%rcx),%rax + mulq 120(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 104(%rcx),%rax + mulq 112(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + addq %rsi,%r12 + adcq %r8,%r9 + adcq %rdi,%r13 + addq %rsi,%r12 + adcq %r8,%r9 + adcq %rdi,%r13 + +/NO_APP + movq %r12, -328(%rbp) +/APP + movq (%rcx),%rax + mulq 224(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 8(%rcx),%rax + mulq 216(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 16(%rcx),%rax + mulq 208(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 24(%rcx),%rax + mulq 200(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 32(%rcx),%rax + mulq 192(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 40(%rcx),%rax + mulq 184(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 48(%rcx),%rax + mulq 176(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 56(%rcx),%rax + mulq 168(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 64(%rcx),%rax + mulq 160(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 72(%rcx),%rax + mulq 152(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 80(%rcx),%rax + mulq 144(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 88(%rcx),%rax + mulq 136(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 96(%rcx),%rax + mulq 128(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 104(%rcx),%rax + mulq 120(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + +/NO_APP + movq %r13, %rax + movq %r10, %rdx + movq %r8, %rbx + movq %rdi, %r12 +/APP + addq %rsi,%r9 + adcq %rbx,%rax + adcq %r12,%rdx + addq %rsi,%r9 + adcq %rbx,%rax + adcq %r12,%rdx + +/NO_APP + movq %rdx, %rdi + movq %r12, %r11 + movq %rbx, %r8 + movq %rax, %r12 + movq %rdi, %r13 + movq %r11, %rdi +/APP + movq 112(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r9, -320(%rbp) + movq %r13, %rbx + movq %r10, %r9 +/APP + movq (%rcx),%rax + mulq 232(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 8(%rcx),%rax + mulq 224(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 16(%rcx),%rax + mulq 216(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 24(%rcx),%rax + mulq 208(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 32(%rcx),%rax + mulq 200(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 40(%rcx),%rax + mulq 192(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 48(%rcx),%rax + mulq 184(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 56(%rcx),%rax + mulq 176(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 64(%rcx),%rax + mulq 168(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 72(%rcx),%rax + mulq 160(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 80(%rcx),%rax + mulq 152(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 88(%rcx),%rax + mulq 144(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 96(%rcx),%rax + mulq 136(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 104(%rcx),%rax + mulq 128(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 112(%rcx),%rax + mulq 120(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + addq %rsi,%r12 + adcq %r8,%rbx + adcq %rdi,%r9 + addq %rsi,%r12 + adcq %r8,%rbx + adcq %rdi,%r9 + +/NO_APP + movq %r12, -312(%rbp) + movq %r9, %r13 +/APP + movq (%rcx),%rax + mulq 240(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 8(%rcx),%rax + mulq 232(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 16(%rcx),%rax + mulq 224(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 24(%rcx),%rax + mulq 216(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 32(%rcx),%rax + mulq 208(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 40(%rcx),%rax + mulq 200(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 48(%rcx),%rax + mulq 192(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 56(%rcx),%rax + mulq 184(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 64(%rcx),%rax + mulq 176(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 72(%rcx),%rax + mulq 168(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 80(%rcx),%rax + mulq 160(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 88(%rcx),%rax + mulq 152(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 96(%rcx),%rax + mulq 144(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 104(%rcx),%rax + mulq 136(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 112(%rcx),%rax + mulq 128(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + +/NO_APP + movq %r10, %rax + movq %r8, %r11 + movq %rdi, %rdx +/APP + addq %rsi,%rbx + adcq %r11,%r13 + adcq %rdx,%rax + addq %rsi,%rbx + adcq %r11,%r13 + adcq %rdx,%rax + +/NO_APP + movq %rdx, %r9 + movq %rax, %rdx + movq %r13, %r12 + movq %r11, %r8 + movq %rdx, %r13 + movq %r9, %rdi +/APP + movq 120(%rcx),%rax + mulq %rax + addq %rax,%rbx + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %rbx, -304(%rbp) + movq %r13, %rbx + movq %r10, %r13 +/APP + movq (%rcx),%rax + mulq 248(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 8(%rcx),%rax + mulq 240(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 16(%rcx),%rax + mulq 232(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 24(%rcx),%rax + mulq 224(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 32(%rcx),%rax + mulq 216(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 40(%rcx),%rax + mulq 208(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 48(%rcx),%rax + mulq 200(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 56(%rcx),%rax + mulq 192(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 64(%rcx),%rax + mulq 184(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 72(%rcx),%rax + mulq 176(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 80(%rcx),%rax + mulq 168(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 88(%rcx),%rax + mulq 160(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 96(%rcx),%rax + mulq 152(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 104(%rcx),%rax + mulq 144(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 112(%rcx),%rax + mulq 136(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 120(%rcx),%rax + mulq 128(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + addq %rsi,%r12 + adcq %r8,%rbx + adcq %rdi,%r13 + addq %rsi,%r12 + adcq %r8,%rbx + adcq %rdi,%r13 + +/NO_APP + movq %r12, -296(%rbp) + movq %r13, %r12 + movq %r10, %r13 +/APP + movq 8(%rcx),%rax + mulq 248(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 16(%rcx),%rax + mulq 240(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 24(%rcx),%rax + mulq 232(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 32(%rcx),%rax + mulq 224(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 40(%rcx),%rax + mulq 216(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 48(%rcx),%rax + mulq 208(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 56(%rcx),%rax + mulq 200(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 64(%rcx),%rax + mulq 192(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 72(%rcx),%rax + mulq 184(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 80(%rcx),%rax + mulq 176(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 88(%rcx),%rax + mulq 168(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 96(%rcx),%rax + mulq 160(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 104(%rcx),%rax + mulq 152(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 112(%rcx),%rax + mulq 144(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 120(%rcx),%rax + mulq 136(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + +/NO_APP + movq %r8, %r11 + movq %rdi, %rax +/APP + addq %rsi,%rbx + adcq %r11,%r12 + adcq %rax,%r13 + addq %rsi,%rbx + adcq %r11,%r12 + adcq %rax,%r13 + +/NO_APP + movq %rax, %r9 + movq %r11, %r8 +/APP + movq 128(%rcx),%rax + mulq %rax + addq %rax,%rbx + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r9, %rdi + movq %rbx, -288(%rbp) + movq %r13, %r9 +/APP + movq 16(%rcx),%rax + mulq 248(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + +/NO_APP + movq %r10, %r13 +/APP + movq 24(%rcx),%rax + mulq 240(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 32(%rcx),%rax + mulq 232(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 40(%rcx),%rax + mulq 224(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 48(%rcx),%rax + mulq 216(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 56(%rcx),%rax + mulq 208(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 64(%rcx),%rax + mulq 200(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 72(%rcx),%rax + mulq 192(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 80(%rcx),%rax + mulq 184(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 88(%rcx),%rax + mulq 176(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 96(%rcx),%rax + mulq 168(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 104(%rcx),%rax + mulq 160(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 112(%rcx),%rax + mulq 152(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 120(%rcx),%rax + mulq 144(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 128(%rcx),%rax + mulq 136(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + addq %rsi,%r12 + adcq %r8,%r9 + adcq %rdi,%r13 + addq %rsi,%r12 + adcq %r8,%r9 + adcq %rdi,%r13 + +/NO_APP + movq %r12, -280(%rbp) + movq %r10, %r12 +/APP + movq 24(%rcx),%rax + mulq 248(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 32(%rcx),%rax + mulq 240(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 40(%rcx),%rax + mulq 232(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 48(%rcx),%rax + mulq 224(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 56(%rcx),%rax + mulq 216(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 64(%rcx),%rax + mulq 208(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 72(%rcx),%rax + mulq 200(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 80(%rcx),%rax + mulq 192(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 88(%rcx),%rax + mulq 184(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 96(%rcx),%rax + mulq 176(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 104(%rcx),%rax + mulq 168(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 112(%rcx),%rax + mulq 160(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 120(%rcx),%rax + mulq 152(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 128(%rcx),%rax + mulq 144(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + +/NO_APP + movq %r13, %rdx + movq %r8, %rbx + movq %rdi, %r13 +/APP + addq %rsi,%r9 + adcq %rbx,%rdx + adcq %r13,%r12 + addq %rsi,%r9 + adcq %rbx,%rdx + adcq %r13,%r12 + +/NO_APP + movq %r12, %rax + movq %r13, %r11 + movq %rdx, %r12 + movq %rax, %r13 + movq %rbx, %r8 + movq %r11, %rdi +/APP + movq 136(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r9, -272(%rbp) + movq %r13, %r9 + movq %r10, %r13 +/APP + movq 32(%rcx),%rax + mulq 248(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 40(%rcx),%rax + mulq 240(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 48(%rcx),%rax + mulq 232(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 56(%rcx),%rax + mulq 224(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 64(%rcx),%rax + mulq 216(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 72(%rcx),%rax + mulq 208(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 80(%rcx),%rax + mulq 200(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 88(%rcx),%rax + mulq 192(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 96(%rcx),%rax + mulq 184(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 104(%rcx),%rax + mulq 176(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 112(%rcx),%rax + mulq 168(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 120(%rcx),%rax + mulq 160(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 128(%rcx),%rax + mulq 152(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 136(%rcx),%rax + mulq 144(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + addq %rsi,%r12 + adcq %r8,%r9 + adcq %rdi,%r13 + addq %rsi,%r12 + adcq %r8,%r9 + adcq %rdi,%r13 + +/NO_APP + movq %r12, -264(%rbp) +/APP + movq 40(%rcx),%rax + mulq 248(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 48(%rcx),%rax + mulq 240(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 56(%rcx),%rax + mulq 232(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 64(%rcx),%rax + mulq 224(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 72(%rcx),%rax + mulq 216(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 80(%rcx),%rax + mulq 208(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 88(%rcx),%rax + mulq 200(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 96(%rcx),%rax + mulq 192(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 104(%rcx),%rax + mulq 184(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 112(%rcx),%rax + mulq 176(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 120(%rcx),%rax + mulq 168(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 128(%rcx),%rax + mulq 160(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 136(%rcx),%rax + mulq 152(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + +/NO_APP + movq %r13, %rax + movq %r10, %rdx + movq %r8, %rbx + movq %rdi, %r12 +/APP + addq %rsi,%r9 + adcq %rbx,%rax + adcq %r12,%rdx + addq %rsi,%r9 + adcq %rbx,%rax + adcq %r12,%rdx + +/NO_APP + movq %rdx, %rdi + movq %r12, %r11 + movq %rbx, %r8 + movq %rax, %r12 + movq %rdi, %r13 + movq %r11, %rdi +/APP + movq 144(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r10, %r11 + movq %r9, -256(%rbp) + movq %r13, %r9 +/APP + movq 48(%rcx),%rax + mulq 248(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 56(%rcx),%rax + mulq 240(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 64(%rcx),%rax + mulq 232(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 72(%rcx),%rax + mulq 224(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 80(%rcx),%rax + mulq 216(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 88(%rcx),%rax + mulq 208(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 96(%rcx),%rax + mulq 200(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 104(%rcx),%rax + mulq 192(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 112(%rcx),%rax + mulq 184(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 120(%rcx),%rax + mulq 176(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 128(%rcx),%rax + mulq 168(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 136(%rcx),%rax + mulq 160(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 144(%rcx),%rax + mulq 152(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + addq %rsi,%r12 + adcq %r8,%r9 + adcq %rdi,%r11 + addq %rsi,%r12 + adcq %r8,%r9 + adcq %rdi,%r11 + +/NO_APP + movq %r12, -248(%rbp) + movq %r11, %r13 +/APP + movq 56(%rcx),%rax + mulq 248(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 64(%rcx),%rax + mulq 240(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 72(%rcx),%rax + mulq 232(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 80(%rcx),%rax + mulq 224(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 88(%rcx),%rax + mulq 216(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 96(%rcx),%rax + mulq 208(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 104(%rcx),%rax + mulq 200(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 112(%rcx),%rax + mulq 192(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 120(%rcx),%rax + mulq 184(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 128(%rcx),%rax + mulq 176(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 136(%rcx),%rax + mulq 168(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 144(%rcx),%rax + mulq 160(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + +/NO_APP + movq %r10, %rax + movq %rsi, %rdx + movq %r8, %rbx + movq %rdi, %r12 +/APP + addq %rdx,%r9 + adcq %rbx,%r13 + adcq %r12,%rax + addq %rdx,%r9 + adcq %rbx,%r13 + adcq %r12,%rax + +/NO_APP + movq %r12, %r11 + movq %rdx, %r8 + movq %rax, %rdx + movq %r13, %r12 + movq %rbx, %rdi + movq %rdx, %r13 + movq %r11, %rsi +/APP + movq 152(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r9, -240(%rbp) + movq %r13, %r9 + movq %r10, %r13 +/APP + movq 64(%rcx),%rax + mulq 248(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 72(%rcx),%rax + mulq 240(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 80(%rcx),%rax + mulq 232(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 88(%rcx),%rax + mulq 224(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 96(%rcx),%rax + mulq 216(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 104(%rcx),%rax + mulq 208(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 112(%rcx),%rax + mulq 200(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 120(%rcx),%rax + mulq 192(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 128(%rcx),%rax + mulq 184(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 136(%rcx),%rax + mulq 176(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 144(%rcx),%rax + mulq 168(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 152(%rcx),%rax + mulq 160(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r8, %rax + movq %rdi, %rdx + movq %rsi, %rbx +/APP + addq %rax,%r12 + adcq %rdx,%r9 + adcq %rbx,%r13 + addq %rax,%r12 + adcq %rdx,%r9 + adcq %rbx,%r13 + +/NO_APP + movq %r12, -232(%rbp) + movq %rdx, %r8 + movq %rax, %rsi + movq %rbx, %rdi + movq %r13, %r12 + movq %r10, %r13 +/APP + movq 72(%rcx),%rax + mulq 248(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 80(%rcx),%rax + mulq 240(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 88(%rcx),%rax + mulq 232(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 96(%rcx),%rax + mulq 224(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 104(%rcx),%rax + mulq 216(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 112(%rcx),%rax + mulq 208(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 120(%rcx),%rax + mulq 200(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 128(%rcx),%rax + mulq 192(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 136(%rcx),%rax + mulq 184(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 144(%rcx),%rax + mulq 176(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 152(%rcx),%rax + mulq 168(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + +/NO_APP + movq %rsi, %rax + movq %r8, %rbx + movq %rdi, %rdx +/APP + addq %rax,%r9 + adcq %rbx,%r12 + adcq %rdx,%r13 + addq %rax,%r9 + adcq %rbx,%r12 + adcq %rdx,%r13 + +/NO_APP + movq %rdx, %r11 + movq %rax, %r8 + movq %rbx, %rdi +/APP + movq 160(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r11, %rsi + movq %r9, -224(%rbp) + movq %r13, %r9 +/APP + movq 80(%rcx),%rax + mulq 248(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + +/NO_APP + movq %r10, %r13 +/APP + movq 88(%rcx),%rax + mulq 240(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 96(%rcx),%rax + mulq 232(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 104(%rcx),%rax + mulq 224(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 112(%rcx),%rax + mulq 216(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 120(%rcx),%rax + mulq 208(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 128(%rcx),%rax + mulq 200(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 136(%rcx),%rax + mulq 192(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 144(%rcx),%rax + mulq 184(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 152(%rcx),%rax + mulq 176(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 160(%rcx),%rax + mulq 168(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r8, %rbx + movq %rdi, %rax + movq %rsi, %rdx +/APP + addq %rbx,%r12 + adcq %rax,%r9 + adcq %rdx,%r13 + addq %rbx,%r12 + adcq %rax,%r9 + adcq %rdx,%r13 + +/NO_APP + movq %r12, -216(%rbp) + movq %rdx, %rdi + movq %rax, %r8 + movq %rbx, %rsi + movq %r13, %r12 + movq %r10, %r13 +/APP + movq 88(%rcx),%rax + mulq 248(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 96(%rcx),%rax + mulq 240(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 104(%rcx),%rax + mulq 232(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 112(%rcx),%rax + mulq 224(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 120(%rcx),%rax + mulq 216(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 128(%rcx),%rax + mulq 208(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 136(%rcx),%rax + mulq 200(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 144(%rcx),%rax + mulq 192(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 152(%rcx),%rax + mulq 184(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 160(%rcx),%rax + mulq 176(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + +/NO_APP + movq %rsi, %rax + movq %r8, %rbx + movq %rdi, %rdx +/APP + addq %rax,%r9 + adcq %rbx,%r12 + adcq %rdx,%r13 + addq %rax,%r9 + adcq %rbx,%r12 + adcq %rdx,%r13 + +/NO_APP + movq %rdx, %r11 + movq %rax, %r8 + movq %rbx, %rdi +/APP + movq 168(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r11, %rsi + movq %r9, -208(%rbp) + movq %r13, %r9 +/APP + movq 96(%rcx),%rax + mulq 248(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + +/NO_APP + movq %r10, %r13 +/APP + movq 104(%rcx),%rax + mulq 240(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 112(%rcx),%rax + mulq 232(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 120(%rcx),%rax + mulq 224(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 128(%rcx),%rax + mulq 216(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 136(%rcx),%rax + mulq 208(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 144(%rcx),%rax + mulq 200(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 152(%rcx),%rax + mulq 192(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 160(%rcx),%rax + mulq 184(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 168(%rcx),%rax + mulq 176(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r8, %rbx + movq %rdi, %rax + movq %rsi, %rdx +/APP + addq %rbx,%r12 + adcq %rax,%r9 + adcq %rdx,%r13 + addq %rbx,%r12 + adcq %rax,%r9 + adcq %rdx,%r13 + +/NO_APP + movq %r12, -200(%rbp) + movq %rdx, %rdi + movq %rax, %r8 + movq %rbx, %rsi + movq %r13, %r12 + movq %r10, %r13 +/APP + movq 104(%rcx),%rax + mulq 248(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 112(%rcx),%rax + mulq 240(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 120(%rcx),%rax + mulq 232(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 128(%rcx),%rax + mulq 224(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 136(%rcx),%rax + mulq 216(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 144(%rcx),%rax + mulq 208(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 152(%rcx),%rax + mulq 200(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 160(%rcx),%rax + mulq 192(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 168(%rcx),%rax + mulq 184(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + +/NO_APP + movq %rsi, %rax + movq %r8, %rbx + movq %rdi, %rdx +/APP + addq %rax,%r9 + adcq %rbx,%r12 + adcq %rdx,%r13 + addq %rax,%r9 + adcq %rbx,%r12 + adcq %rdx,%r13 + +/NO_APP + movq %rdx, %r11 + movq %rax, %r8 + movq %rbx, %rdi +/APP + movq 176(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r11, %rsi + movq %r9, -192(%rbp) + movq %r13, %r9 +/APP + movq 112(%rcx),%rax + mulq 248(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + +/NO_APP + movq %r10, %r13 +/APP + movq 120(%rcx),%rax + mulq 240(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 128(%rcx),%rax + mulq 232(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 136(%rcx),%rax + mulq 224(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 144(%rcx),%rax + mulq 216(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 152(%rcx),%rax + mulq 208(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 160(%rcx),%rax + mulq 200(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 168(%rcx),%rax + mulq 192(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 176(%rcx),%rax + mulq 184(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r8, %rbx + movq %rdi, %rax + movq %rsi, %rdx +/APP + addq %rbx,%r12 + adcq %rax,%r9 + adcq %rdx,%r13 + addq %rbx,%r12 + adcq %rax,%r9 + adcq %rdx,%r13 + +/NO_APP + movq %r12, -184(%rbp) + movq %rdx, %rdi + movq %rax, %r8 + movq %rbx, %rsi + movq %r13, %r12 + movq %r10, %r13 +/APP + movq 120(%rcx),%rax + mulq 248(%rcx) + movq %rax,%rsi + movq %rdx,%r8 + xorq %rdi,%rdi + + movq 128(%rcx),%rax + mulq 240(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 136(%rcx),%rax + mulq 232(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 144(%rcx),%rax + mulq 224(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 152(%rcx),%rax + mulq 216(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 160(%rcx),%rax + mulq 208(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 168(%rcx),%rax + mulq 200(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + + movq 176(%rcx),%rax + mulq 192(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%rdi + +/NO_APP + movq %rsi, %rax + movq %r8, %rbx + movq %rdi, %rdx +/APP + addq %rax,%r9 + adcq %rbx,%r12 + adcq %rdx,%r13 + addq %rax,%r9 + adcq %rbx,%r12 + adcq %rdx,%r13 + +/NO_APP + movq %rdx, %r11 + movq %rax, %r8 + movq %rbx, %rdi +/APP + movq 184(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r11, %rsi + movq %r9, -176(%rbp) + movq %r13, %r9 +/APP + movq 128(%rcx),%rax + mulq 248(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + +/NO_APP + movq %r10, %r13 +/APP + movq 136(%rcx),%rax + mulq 240(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 144(%rcx),%rax + mulq 232(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 152(%rcx),%rax + mulq 224(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 160(%rcx),%rax + mulq 216(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 168(%rcx),%rax + mulq 208(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 176(%rcx),%rax + mulq 200(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 184(%rcx),%rax + mulq 192(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + addq %r8,%r12 + adcq %rdi,%r9 + adcq %rsi,%r13 + addq %r8,%r12 + adcq %rdi,%r9 + adcq %rsi,%r13 + +/NO_APP + movq %r12, -168(%rbp) + movq %r13, %r12 + movq %r10, %r13 +/APP + movq 136(%rcx),%rax + mulq 248(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 144(%rcx),%rax + mulq 240(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 152(%rcx),%rax + mulq 232(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 160(%rcx),%rax + mulq 224(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 168(%rcx),%rax + mulq 216(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 176(%rcx),%rax + mulq 208(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 184(%rcx),%rax + mulq 200(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %rbx + movq %rsi, %rax +/APP + addq %r8,%r9 + adcq %rbx,%r12 + adcq %rax,%r13 + addq %r8,%r9 + adcq %rbx,%r12 + adcq %rax,%r13 + +/NO_APP + movq %rax, %r11 + movq %rbx, %rdi + movq %r10, %rbx +/APP + movq 192(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r11, %rsi + movq %r9, -160(%rbp) + movq %r13, %r9 +/APP + movq 144(%rcx),%rax + mulq 248(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 152(%rcx),%rax + mulq 240(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 160(%rcx),%rax + mulq 232(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 168(%rcx),%rax + mulq 224(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 176(%rcx),%rax + mulq 216(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 184(%rcx),%rax + mulq 208(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 192(%rcx),%rax + mulq 200(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + addq %r8,%r12 + adcq %rdi,%r9 + adcq %rsi,%rbx + addq %r8,%r12 + adcq %rdi,%r9 + adcq %rsi,%rbx + +/NO_APP + movq %r12, -152(%rbp) +/APP + movq 152(%rcx),%rax + mulq 248(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 160(%rcx),%rax + mulq 240(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 168(%rcx),%rax + mulq 232(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 176(%rcx),%rax + mulq 224(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 184(%rcx),%rax + mulq 216(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 192(%rcx),%rax + mulq 208(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r10, %rdx + movq %rdi, %r13 + movq %rsi, %r12 +/APP + addq %r8,%r9 + adcq %r13,%rbx + adcq %r12,%rdx + addq %r8,%r9 + adcq %r13,%rbx + adcq %r12,%rdx + +/NO_APP + movq %rdx, %rax + movq %r13, %rdi + movq %r12, %rsi + movq %rax, %r11 + movq %r10, %r12 +/APP + movq 200(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%rbx + adcq $0,%r11 + +/NO_APP + movq %r9, -144(%rbp) + movq %r11, %r9 +/APP + movq 160(%rcx),%rax + mulq 248(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 168(%rcx),%rax + mulq 240(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 176(%rcx),%rax + mulq 232(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 184(%rcx),%rax + mulq 224(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 192(%rcx),%rax + mulq 216(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 200(%rcx),%rax + mulq 208(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + addq %r8,%rbx + adcq %rdi,%r9 + adcq %rsi,%r12 + addq %r8,%rbx + adcq %rdi,%r9 + adcq %rsi,%r12 + +/NO_APP + movq %rbx, -136(%rbp) + movq %r12, %r11 +/APP + movq 168(%rcx),%rax + mulq 248(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 176(%rcx),%rax + mulq 240(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 184(%rcx),%rax + mulq 232(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 192(%rcx),%rax + mulq 224(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 200(%rcx),%rax + mulq 216(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r10, %rax + movq %rdi, %r13 + movq %rsi, %r12 +/APP + addq %r8,%r9 + adcq %r13,%r11 + adcq %r12,%rax + addq %r8,%r9 + adcq %r13,%r11 + adcq %r12,%rax + +/NO_APP + movq %rax, %rdx + movq %r11, %rbx + movq %r13, %rdi + movq %rdx, %r11 + movq %r12, %rsi +/APP + movq 208(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%rbx + adcq $0,%r11 + +/NO_APP + movq %r9, -128(%rbp) + movq %r11, %r9 +/APP + movq 176(%rcx),%rax + mulq 248(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 184(%rcx),%rax + mulq 240(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 192(%rcx),%rax + mulq 232(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 200(%rcx),%rax + mulq 224(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 208(%rcx),%rax + mulq 216(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r10, %rdx +/APP + addq %r8,%rbx + adcq %rdi,%r9 + adcq %rsi,%rdx + addq %r8,%rbx + adcq %rdi,%r9 + adcq %rsi,%rdx + +/NO_APP + movq %rbx, -120(%rbp) + movq %rdx, %r11 + movq %r10, %rbx +/APP + movq 184(%rcx),%rax + mulq 248(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 192(%rcx),%rax + mulq 240(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 200(%rcx),%rax + mulq 232(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 208(%rcx),%rax + mulq 224(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r13 + movq %rsi, %r12 +/APP + addq %r8,%r9 + adcq %r13,%r11 + adcq %r12,%rbx + addq %r8,%r9 + adcq %r13,%r11 + adcq %r12,%rbx + +/NO_APP + movq %rbx, %rdx + movq %r13, %rdi + movq %r11, %rbx + movq %r12, %rsi + movq %rdx, %r11 + movq %r10, %r12 +/APP + movq 216(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%rbx + adcq $0,%r11 + +/NO_APP + movq %r9, -112(%rbp) + movq %r11, %r9 +/APP + movq 192(%rcx),%rax + mulq 248(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 200(%rcx),%rax + mulq 240(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 208(%rcx),%rax + mulq 232(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 216(%rcx),%rax + mulq 224(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + addq %r8,%rbx + adcq %rdi,%r9 + adcq %rsi,%r12 + addq %r8,%rbx + adcq %rdi,%r9 + adcq %rsi,%r12 + +/NO_APP + movq %rbx, -104(%rbp) + movq %r12, %r11 +/APP + movq 200(%rcx),%rax + mulq 248(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 208(%rcx),%rax + mulq 240(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 216(%rcx),%rax + mulq 232(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %r10, %rax + movq %rdi, %r13 + movq %rsi, %r12 +/APP + addq %r8,%r9 + adcq %r13,%r11 + adcq %r12,%rax + addq %r8,%r9 + adcq %r13,%r11 + adcq %r12,%rax + +/NO_APP + movq %rax, %rdx + movq %r11, %rbx + movq %r13, %rdi + movq %rdx, %r11 + movq %r12, %rsi + movq %r10, %r12 +/APP + movq 224(%rcx),%rax + mulq %rax + addq %rax,%r9 + adcq %rdx,%rbx + adcq $0,%r11 + +/NO_APP + movq %r9, -96(%rbp) + movq %r10, %r9 +/APP + movq 208(%rcx),%rax + mulq 248(%rcx) + movq %rax,%r8 + movq %rdx,%rdi + xorq %rsi,%rsi + + movq 216(%rcx),%rax + mulq 240(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + + movq 224(%rcx),%rax + mulq 232(%rcx) + addq %rax,%r8 + adcq %rdx,%rdi + adcq $0,%rsi + +/NO_APP + movq %rdi, %r13 + movq %rsi, %rax +/APP + addq %r8,%rbx + adcq %r13,%r11 + adcq %rax,%r9 + addq %r8,%rbx + adcq %r13,%r11 + adcq %rax,%r9 + +/NO_APP + movq %rbx, -88(%rbp) + movq %r11, %rsi + movq %r9, %r8 +/APP + movq 216(%rcx),%rax + mulq 248(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%r12 + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%r12 + +/NO_APP + movq %r12, %r11 +/APP + movq 224(%rcx),%rax + mulq 240(%rcx) + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%r11 + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%r11 + +/NO_APP + movq %r8, %r13 + movq %r11, %rbx +/APP + movq 232(%rcx),%rax + mulq %rax + addq %rax,%rsi + adcq %rdx,%r13 + adcq $0,%rbx + +/NO_APP + movq %rsi, -80(%rbp) + movq %rbx, %r12 + movq %r13, %rdi + movq %r10, %r13 +/APP + movq 224(%rcx),%rax + mulq 248(%rcx) + addq %rax,%rdi + adcq %rdx,%r12 + adcq $0,%r13 + addq %rax,%rdi + adcq %rdx,%r12 + adcq $0,%r13 + +/NO_APP + movq %r12, %r9 + movq %r13, %r12 +/APP + movq 232(%rcx),%rax + mulq 240(%rcx) + addq %rax,%rdi + adcq %rdx,%r9 + adcq $0,%r12 + addq %rax,%rdi + adcq %rdx,%r9 + adcq $0,%r12 + +/NO_APP + movq %rdi, -72(%rbp) + movq %r9, %r11 + movq %r12, %rbx + movq %r10, %r9 +/APP + movq 232(%rcx),%rax + mulq 248(%rcx) + addq %rax,%r11 + adcq %rdx,%rbx + adcq $0,%r9 + addq %rax,%r11 + adcq %rdx,%rbx + adcq $0,%r9 + +/NO_APP + movq %rbx, %r13 + movq %r9, %rbx + movq %r10, %r9 +/APP + movq 240(%rcx),%rax + mulq %rax + addq %rax,%r11 + adcq %rdx,%r13 + adcq $0,%rbx + +/NO_APP + movq %r11, -64(%rbp) + movq %r13, %rdi + movq %rbx, %rsi +/APP + movq 240(%rcx),%rax + mulq 248(%rcx) + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%r9 + addq %rax,%rdi + adcq %rdx,%rsi + adcq $0,%r9 + +/NO_APP + movq %rdi, -56(%rbp) + movq %r9, %r8 +/APP + movq 248(%rcx),%rax + mulq %rax + addq %rax,%rsi + adcq %rdx,%r8 + adcq $0,%r10 + +/NO_APP + movq %rsi, -48(%rbp) + movq 16(%r14), %rdi + leaq -544(%rbp), %rsi + movl $512, %edx + movq %r8, -40(%rbp) + movl $64, 8(%r14) + movl $0, (%r14) + call memcpy@PLT + movl 8(%r14), %edx + testl %edx, %edx + je .L304 + leal -1(%rdx), %ecx + movq 16(%r14), %rsi + mov %ecx, %r10d + cmpq $0, (%rsi,%r10,8) + jne .L302 + movl %ecx, %edx + .align 16 +.L303: + testl %edx, %edx + movl %edx, %ecx + je .L307 + decl %edx + mov %edx, %eax + cmpq $0, (%rsi,%rax,8) + je .L303 + movl %ecx, 8(%r14) + movl %ecx, %edx +.L302: + testl %edx, %edx + je .L304 + movl (%r14), %eax + movl %eax, (%r14) + addq $512, %rsp + popq %rbx + popq %r12 + popq %r13 + popq %r14 + leave + ret +.L307: + movl %edx, 8(%r14) + .align 16 +.L304: + xorl %eax, %eax + movl %eax, (%r14) + addq $512, %rsp + popq %rbx + popq %r12 + popq %r13 + popq %r14 + leave + ret +.LFE9: + .size s_mp_sqr_comba_32, .-s_mp_sqr_comba_32 diff --git a/security/nss/lib/freebl/mpi/mpcpucache.c b/security/nss/lib/freebl/mpi/mpcpucache.c new file mode 100644 index 000000000..8adbd33c6 --- /dev/null +++ b/security/nss/lib/freebl/mpi/mpcpucache.c @@ -0,0 +1,773 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Red Hat, Inc + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Robert Relyea <rrelyea@redhat.com> + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "mpi.h" + +/* + * This file implements a single function: s_mpi_getProcessorLineSize(); + * s_mpi_getProcessorLineSize() returns the size in bytes of the cache line + * if a cache exists, or zero if there is no cache. If more than one + * cache line exists, it should return the smallest line size (which is + * usually the L1 cache). + * + * mp_modexp uses this information to make sure that private key information + * isn't being leaked through the cache. + * + * Currently the file returns good data for most modern x86 processors, and + * reasonable data on 64-bit ppc processors. All other processors are assumed + * to have a cache line size of 32 bytes unless modified by target.mk. + * + */ + +#if defined(i386) || defined(__i386) || defined(__X86__) || defined (_M_IX86) || defined(__x86_64__) || defined(__x86_64) +/* X86 processors have special instructions that tell us about the cache */ +#include "string.h" + +#if defined(__x86_64__) || defined(__x86_64) +#define AMD_64 1 +#endif + +/* Generic CPUID function */ +#if defined(AMD_64) +static void cpuid(unsigned long op, unsigned long *eax, + unsigned long *ebx, unsigned long *ecx, + unsigned long *edx) +{ + __asm__("cpuid\n\t" + : "=a" (*eax), + "=b" (*ebx), + "=c" (*ecx), + "=d" (*edx) + : "0" (op)); +} +#elif !defined(_MSC_VER) +static void cpuid(unsigned long op, unsigned long *eax, + unsigned long *ebx, unsigned long *ecx, + unsigned long *edx) +{ +/* sigh GCC isn't smart enough to save the ebx PIC register on it's own + * in this case, so do it by hand. */ + __asm__("pushl %%ebx\n\t" + "cpuid\n\t" + "mov %%ebx,%1\n\t" + "popl %%ebx\n\t" + : "=a" (*eax), + "=r" (*ebx), + "=c" (*ecx), + "=d" (*edx) + : "0" (op)); +} + +/* + * try flipping a processor flag to determine CPU type + */ +static unsigned long changeFlag(unsigned long flag) +{ + unsigned long changedFlags, originalFlags; + __asm__("pushfl\n\t" /* get the flags */ + "popl %0\n\t" + "movl %0,%1\n\t" /* save the original flags */ + "xorl %2,%0\n\t" /* flip the bit */ + "pushl %0\n\t" /* set the flags */ + "popfl\n\t" + "pushfl\n\t" /* get the flags again (for return) */ + "popl %0\n\t" + "pushl %1\n\t" /* restore the original flags */ + "popfl\n\t" + : "=r" (changedFlags), + "=r" (originalFlags), + "=r" (flag) + : "2" (flag)); + return changedFlags ^ originalFlags; +} + +#else + +/* + * windows versions of the above assembler + */ +#define wcpuid __asm __emit 0fh __asm __emit 0a2h +static void cpuid(unsigned long op, unsigned long *Reax, + unsigned long *Rebx, unsigned long *Recx, unsigned long *Redx) +{ + unsigned long Leax, Lebx, Lecx, Ledx; + __asm { + pushad + mov eax,op + wcpuid + mov Leax,eax + mov Lebx,ebx + mov Lecx,ecx + mov Ledx,edx + popad + } + *Reax = Leax; + *Rebx = Lebx; + *Recx = Lecx; + *Redx = Ledx; +} + +static unsigned long changeFlag(unsigned long flag) +{ + unsigned long changedFlags, originalFlags; + __asm { + push eax + push ebx + pushfd /* get the flags */ + pop eax + push eax /* save the flags on the stack */ + mov originalFlags,eax /* save the original flags */ + mov ebx,flag + xor eax,ebx /* flip the bit */ + push eax /* set the flags */ + popfd + pushfd /* get the flags again (for return) */ + pop eax + popfd /* restore the original flags */ + mov changedFlags,eax + pop ebx + pop eax + } + return changedFlags ^ originalFlags; +} +#endif + +#if !defined(AMD_64) +#define AC_FLAG 0x40000 +#define ID_FLAG 0x200000 + +/* 386 processors can't flip the AC_FLAG, intel AP Note AP-485 */ +static int is386() +{ + return changeFlag(AC_FLAG) == 0; +} + +/* 486 processors can't flip the ID_FLAG, intel AP Note AP-485 */ +static int is486() +{ + return changeFlag(ID_FLAG) == 0; +} +#endif + + +/* + * table for Intel Cache. + * See Intel Application Note AP-485 for more information + */ + +typedef unsigned char CacheTypeEntry; + +typedef enum { + Cache_NONE = 0, + Cache_UNKNOWN = 1, + Cache_TLB = 2, + Cache_TLBi = 3, + Cache_TLBd = 4, + Cache_Trace = 5, + Cache_L1 = 6, + Cache_L1i = 7, + Cache_L1d = 8, + Cache_L2 = 9 , + Cache_L2i = 10 , + Cache_L2d = 11 , + Cache_L3 = 12 , + Cache_L3i = 13, + Cache_L3d = 14 +} CacheType; + +struct _cache { + CacheTypeEntry type; + unsigned char lineSize; +}; +static const struct _cache CacheMap[256] = { +/* 00 */ {Cache_NONE, 0 }, +/* 01 */ {Cache_TLBi, 0 }, +/* 02 */ {Cache_TLBi, 0 }, +/* 03 */ {Cache_TLBd, 0 }, +/* 04 */ {Cache_TLBd, }, +/* 05 */ {Cache_UNKNOWN, 0 }, +/* 06 */ {Cache_L1i, 32 }, +/* 07 */ {Cache_UNKNOWN, 0 }, +/* 08 */ {Cache_L1i, 32 }, +/* 09 */ {Cache_UNKNOWN, 0 }, +/* 0a */ {Cache_L1d, 32 }, +/* 0b */ {Cache_UNKNOWN, 0 }, +/* 0c */ {Cache_L1d, 32 }, +/* 0d */ {Cache_UNKNOWN, 0 }, +/* 0e */ {Cache_UNKNOWN, 0 }, +/* 0f */ {Cache_UNKNOWN, 0 }, +/* 10 */ {Cache_UNKNOWN, 0 }, +/* 11 */ {Cache_UNKNOWN, 0 }, +/* 12 */ {Cache_UNKNOWN, 0 }, +/* 13 */ {Cache_UNKNOWN, 0 }, +/* 14 */ {Cache_UNKNOWN, 0 }, +/* 15 */ {Cache_UNKNOWN, 0 }, +/* 16 */ {Cache_UNKNOWN, 0 }, +/* 17 */ {Cache_UNKNOWN, 0 }, +/* 18 */ {Cache_UNKNOWN, 0 }, +/* 19 */ {Cache_UNKNOWN, 0 }, +/* 1a */ {Cache_UNKNOWN, 0 }, +/* 1b */ {Cache_UNKNOWN, 0 }, +/* 1c */ {Cache_UNKNOWN, 0 }, +/* 1d */ {Cache_UNKNOWN, 0 }, +/* 1e */ {Cache_UNKNOWN, 0 }, +/* 1f */ {Cache_UNKNOWN, 0 }, +/* 20 */ {Cache_UNKNOWN, 0 }, +/* 21 */ {Cache_UNKNOWN, 0 }, +/* 22 */ {Cache_L3, 64 }, +/* 23 */ {Cache_L3, 64 }, +/* 24 */ {Cache_UNKNOWN, 0 }, +/* 25 */ {Cache_L3, 64 }, +/* 26 */ {Cache_UNKNOWN, 0 }, +/* 27 */ {Cache_UNKNOWN, 0 }, +/* 28 */ {Cache_UNKNOWN, 0 }, +/* 29 */ {Cache_L3, 64 }, +/* 2a */ {Cache_UNKNOWN, 0 }, +/* 2b */ {Cache_UNKNOWN, 0 }, +/* 2c */ {Cache_L1d, 64 }, +/* 2d */ {Cache_UNKNOWN, 0 }, +/* 2e */ {Cache_UNKNOWN, 0 }, +/* 2f */ {Cache_UNKNOWN, 0 }, +/* 30 */ {Cache_L1i, 64 }, +/* 31 */ {Cache_UNKNOWN, 0 }, +/* 32 */ {Cache_UNKNOWN, 0 }, +/* 33 */ {Cache_UNKNOWN, 0 }, +/* 34 */ {Cache_UNKNOWN, 0 }, +/* 35 */ {Cache_UNKNOWN, 0 }, +/* 36 */ {Cache_UNKNOWN, 0 }, +/* 37 */ {Cache_UNKNOWN, 0 }, +/* 38 */ {Cache_UNKNOWN, 0 }, +/* 39 */ {Cache_L2, 64 }, +/* 3a */ {Cache_UNKNOWN, 0 }, +/* 3b */ {Cache_L2, 64 }, +/* 3c */ {Cache_L2, 64 }, +/* 3d */ {Cache_UNKNOWN, 0 }, +/* 3e */ {Cache_UNKNOWN, 0 }, +/* 3f */ {Cache_UNKNOWN, 0 }, +/* 40 */ {Cache_L2, 0 }, +/* 41 */ {Cache_L2, 32 }, +/* 42 */ {Cache_L2, 32 }, +/* 43 */ {Cache_L2, 32 }, +/* 44 */ {Cache_L2, 32 }, +/* 45 */ {Cache_L2, 32 }, +/* 46 */ {Cache_UNKNOWN, 0 }, +/* 47 */ {Cache_UNKNOWN, 0 }, +/* 48 */ {Cache_UNKNOWN, 0 }, +/* 49 */ {Cache_UNKNOWN, 0 }, +/* 4a */ {Cache_UNKNOWN, 0 }, +/* 4b */ {Cache_UNKNOWN, 0 }, +/* 4c */ {Cache_UNKNOWN, 0 }, +/* 4d */ {Cache_UNKNOWN, 0 }, +/* 4e */ {Cache_UNKNOWN, 0 }, +/* 4f */ {Cache_UNKNOWN, 0 }, +/* 50 */ {Cache_TLBi, 0 }, +/* 51 */ {Cache_TLBi, 0 }, +/* 52 */ {Cache_TLBi, 0 }, +/* 53 */ {Cache_UNKNOWN, 0 }, +/* 54 */ {Cache_UNKNOWN, 0 }, +/* 55 */ {Cache_UNKNOWN, 0 }, +/* 56 */ {Cache_UNKNOWN, 0 }, +/* 57 */ {Cache_UNKNOWN, 0 }, +/* 58 */ {Cache_UNKNOWN, 0 }, +/* 59 */ {Cache_UNKNOWN, 0 }, +/* 5a */ {Cache_UNKNOWN, 0 }, +/* 5b */ {Cache_TLBd, 0 }, +/* 5c */ {Cache_TLBd, 0 }, +/* 5d */ {Cache_TLBd, 0 }, +/* 5e */ {Cache_UNKNOWN, 0 }, +/* 5f */ {Cache_UNKNOWN, 0 }, +/* 60 */ {Cache_UNKNOWN, 0 }, +/* 61 */ {Cache_UNKNOWN, 0 }, +/* 62 */ {Cache_UNKNOWN, 0 }, +/* 63 */ {Cache_UNKNOWN, 0 }, +/* 64 */ {Cache_UNKNOWN, 0 }, +/* 65 */ {Cache_UNKNOWN, 0 }, +/* 66 */ {Cache_L1d, 64 }, +/* 67 */ {Cache_L1d, 64 }, +/* 68 */ {Cache_L1d, 64 }, +/* 69 */ {Cache_UNKNOWN, 0 }, +/* 6a */ {Cache_UNKNOWN, 0 }, +/* 6b */ {Cache_UNKNOWN, 0 }, +/* 6c */ {Cache_UNKNOWN, 0 }, +/* 6d */ {Cache_UNKNOWN, 0 }, +/* 6e */ {Cache_UNKNOWN, 0 }, +/* 6f */ {Cache_UNKNOWN, 0 }, +/* 70 */ {Cache_Trace, 1 }, +/* 71 */ {Cache_Trace, 1 }, +/* 72 */ {Cache_Trace, 1 }, +/* 73 */ {Cache_UNKNOWN, 0 }, +/* 74 */ {Cache_UNKNOWN, 0 }, +/* 75 */ {Cache_UNKNOWN, 0 }, +/* 76 */ {Cache_UNKNOWN, 0 }, +/* 77 */ {Cache_UNKNOWN, 0 }, +/* 78 */ {Cache_UNKNOWN, 0 }, +/* 79 */ {Cache_L2, 64 }, +/* 7a */ {Cache_L2, 64 }, +/* 7b */ {Cache_L2, 64 }, +/* 7c */ {Cache_L2, 64 }, +/* 7d */ {Cache_UNKNOWN, 0 }, +/* 7e */ {Cache_UNKNOWN, 0 }, +/* 7f */ {Cache_UNKNOWN, 0 }, +/* 80 */ {Cache_UNKNOWN, 0 }, +/* 81 */ {Cache_UNKNOWN, 0 }, +/* 82 */ {Cache_L2, 32 }, +/* 83 */ {Cache_L2, 32 }, +/* 84 */ {Cache_L2, 32 }, +/* 85 */ {Cache_L2, 32 }, +/* 86 */ {Cache_L2, 64 }, +/* 87 */ {Cache_L2, 64 }, +/* 88 */ {Cache_UNKNOWN, 0 }, +/* 89 */ {Cache_UNKNOWN, 0 }, +/* 8a */ {Cache_UNKNOWN, 0 }, +/* 8b */ {Cache_UNKNOWN, 0 }, +/* 8c */ {Cache_UNKNOWN, 0 }, +/* 8d */ {Cache_UNKNOWN, 0 }, +/* 8e */ {Cache_UNKNOWN, 0 }, +/* 8f */ {Cache_UNKNOWN, 0 }, +/* 90 */ {Cache_UNKNOWN, 0 }, +/* 91 */ {Cache_UNKNOWN, 0 }, +/* 92 */ {Cache_UNKNOWN, 0 }, +/* 93 */ {Cache_UNKNOWN, 0 }, +/* 94 */ {Cache_UNKNOWN, 0 }, +/* 95 */ {Cache_UNKNOWN, 0 }, +/* 96 */ {Cache_UNKNOWN, 0 }, +/* 97 */ {Cache_UNKNOWN, 0 }, +/* 98 */ {Cache_UNKNOWN, 0 }, +/* 99 */ {Cache_UNKNOWN, 0 }, +/* 9a */ {Cache_UNKNOWN, 0 }, +/* 9b */ {Cache_UNKNOWN, 0 }, +/* 9c */ {Cache_UNKNOWN, 0 }, +/* 9d */ {Cache_UNKNOWN, 0 }, +/* 9e */ {Cache_UNKNOWN, 0 }, +/* 9f */ {Cache_UNKNOWN, 0 }, +/* a0 */ {Cache_UNKNOWN, 0 }, +/* a1 */ {Cache_UNKNOWN, 0 }, +/* a2 */ {Cache_UNKNOWN, 0 }, +/* a3 */ {Cache_UNKNOWN, 0 }, +/* a4 */ {Cache_UNKNOWN, 0 }, +/* a5 */ {Cache_UNKNOWN, 0 }, +/* a6 */ {Cache_UNKNOWN, 0 }, +/* a7 */ {Cache_UNKNOWN, 0 }, +/* a8 */ {Cache_UNKNOWN, 0 }, +/* a9 */ {Cache_UNKNOWN, 0 }, +/* aa */ {Cache_UNKNOWN, 0 }, +/* ab */ {Cache_UNKNOWN, 0 }, +/* ac */ {Cache_UNKNOWN, 0 }, +/* ad */ {Cache_UNKNOWN, 0 }, +/* ae */ {Cache_UNKNOWN, 0 }, +/* af */ {Cache_UNKNOWN, 0 }, +/* b0 */ {Cache_TLBi, 0 }, +/* b1 */ {Cache_UNKNOWN, 0 }, +/* b2 */ {Cache_UNKNOWN, 0 }, +/* b3 */ {Cache_TLBd, 0 }, +/* b4 */ {Cache_UNKNOWN, 0 }, +/* b5 */ {Cache_UNKNOWN, 0 }, +/* b6 */ {Cache_UNKNOWN, 0 }, +/* b7 */ {Cache_UNKNOWN, 0 }, +/* b8 */ {Cache_UNKNOWN, 0 }, +/* b9 */ {Cache_UNKNOWN, 0 }, +/* ba */ {Cache_UNKNOWN, 0 }, +/* bb */ {Cache_UNKNOWN, 0 }, +/* bc */ {Cache_UNKNOWN, 0 }, +/* bd */ {Cache_UNKNOWN, 0 }, +/* be */ {Cache_UNKNOWN, 0 }, +/* bf */ {Cache_UNKNOWN, 0 }, +/* c0 */ {Cache_UNKNOWN, 0 }, +/* c1 */ {Cache_UNKNOWN, 0 }, +/* c2 */ {Cache_UNKNOWN, 0 }, +/* c3 */ {Cache_UNKNOWN, 0 }, +/* c4 */ {Cache_UNKNOWN, 0 }, +/* c5 */ {Cache_UNKNOWN, 0 }, +/* c6 */ {Cache_UNKNOWN, 0 }, +/* c7 */ {Cache_UNKNOWN, 0 }, +/* c8 */ {Cache_UNKNOWN, 0 }, +/* c9 */ {Cache_UNKNOWN, 0 }, +/* ca */ {Cache_UNKNOWN, 0 }, +/* cb */ {Cache_UNKNOWN, 0 }, +/* cc */ {Cache_UNKNOWN, 0 }, +/* cd */ {Cache_UNKNOWN, 0 }, +/* ce */ {Cache_UNKNOWN, 0 }, +/* cf */ {Cache_UNKNOWN, 0 }, +/* d0 */ {Cache_UNKNOWN, 0 }, +/* d1 */ {Cache_UNKNOWN, 0 }, +/* d2 */ {Cache_UNKNOWN, 0 }, +/* d3 */ {Cache_UNKNOWN, 0 }, +/* d4 */ {Cache_UNKNOWN, 0 }, +/* d5 */ {Cache_UNKNOWN, 0 }, +/* d6 */ {Cache_UNKNOWN, 0 }, +/* d7 */ {Cache_UNKNOWN, 0 }, +/* d8 */ {Cache_UNKNOWN, 0 }, +/* d9 */ {Cache_UNKNOWN, 0 }, +/* da */ {Cache_UNKNOWN, 0 }, +/* db */ {Cache_UNKNOWN, 0 }, +/* dc */ {Cache_UNKNOWN, 0 }, +/* dd */ {Cache_UNKNOWN, 0 }, +/* de */ {Cache_UNKNOWN, 0 }, +/* df */ {Cache_UNKNOWN, 0 }, +/* e0 */ {Cache_UNKNOWN, 0 }, +/* e1 */ {Cache_UNKNOWN, 0 }, +/* e2 */ {Cache_UNKNOWN, 0 }, +/* e3 */ {Cache_UNKNOWN, 0 }, +/* e4 */ {Cache_UNKNOWN, 0 }, +/* e5 */ {Cache_UNKNOWN, 0 }, +/* e6 */ {Cache_UNKNOWN, 0 }, +/* e7 */ {Cache_UNKNOWN, 0 }, +/* e8 */ {Cache_UNKNOWN, 0 }, +/* e9 */ {Cache_UNKNOWN, 0 }, +/* ea */ {Cache_UNKNOWN, 0 }, +/* eb */ {Cache_UNKNOWN, 0 }, +/* ec */ {Cache_UNKNOWN, 0 }, +/* ed */ {Cache_UNKNOWN, 0 }, +/* ee */ {Cache_UNKNOWN, 0 }, +/* ef */ {Cache_UNKNOWN, 0 }, +/* f0 */ {Cache_UNKNOWN, 0 }, +/* f1 */ {Cache_UNKNOWN, 0 }, +/* f2 */ {Cache_UNKNOWN, 0 }, +/* f3 */ {Cache_UNKNOWN, 0 }, +/* f4 */ {Cache_UNKNOWN, 0 }, +/* f5 */ {Cache_UNKNOWN, 0 }, +/* f6 */ {Cache_UNKNOWN, 0 }, +/* f7 */ {Cache_UNKNOWN, 0 }, +/* f8 */ {Cache_UNKNOWN, 0 }, +/* f9 */ {Cache_UNKNOWN, 0 }, +/* fa */ {Cache_UNKNOWN, 0 }, +/* fb */ {Cache_UNKNOWN, 0 }, +/* fc */ {Cache_UNKNOWN, 0 }, +/* fd */ {Cache_UNKNOWN, 0 }, +/* fe */ {Cache_UNKNOWN, 0 }, +/* ff */ {Cache_UNKNOWN, 0 } +}; + + +/* + * use the above table to determine the CacheEntryLineSize. + */ +static void +getIntelCacheEntryLineSize(unsigned long val, int *level, + unsigned long *lineSize) +{ + CacheType type; + + type = CacheMap[val].type; + /* only interested in data caches */ + /* NOTE val = 0x40 is a special value that means no L2 or L3 cache. + * this data check has the side effect of rejecting that entry. If + * that wasn't the case, we could have to reject it explicitly */ + if (CacheMap[val].lineSize == 0) { + return; + } + /* look at the caches, skip types we aren't interested in. + * if we already have a value for a lower level cache, skip the + * current entry */ + if ((type == Cache_L1)|| (type == Cache_L1d)) { + *level = 1; + *lineSize = CacheMap[val].lineSize; + } else if ((*level >= 2) && ((type == Cache_L2) || (type == Cache_L2d))) { + *level = 2; + *lineSize = CacheMap[val].lineSize; + } else if ((*level >= 3) && ((type == Cache_L3) || (type == Cache_L3d))) { + *level = 3; + *lineSize = CacheMap[val].lineSize; + } + return; +} + + +static void +getIntelRegisterCacheLineSize(unsigned long val, + int *level, unsigned long *lineSize) +{ + getIntelCacheEntryLineSize(val >> 24 & 0xff, level, lineSize); + getIntelCacheEntryLineSize(val >> 16 & 0xff, level, lineSize); + getIntelCacheEntryLineSize(val >> 8 & 0xff, level, lineSize); + getIntelCacheEntryLineSize(val & 0xff, level, lineSize); +} + +/* + * returns '0' if no recognized cache is found, or if the cache + * information is supported by this processor + */ +static unsigned long +getIntelCacheLineSize(int cpuidLevel) +{ + int level = 4; + unsigned long lineSize = 0; + unsigned long eax, ebx, ecx, edx; + int repeat, count; + + if (cpuidLevel < 2) { + return 0; + } + + /* command '2' of the cpuid is intel's cache info call. Each byte of the + * 4 registers contain a potential descriptor for the cache. The CacheMap + * table maps the cache entry with the processor cache. Register 'al' + * contains a count value that cpuid '2' needs to be called in order to + * find all the cache descriptors. Only registers with the high bit set + * to 'zero' have valid descriptors. This code loops through all the + * required calls to cpuid '2' and passes any valid descriptors it finds + * to the getIntelRegisterCacheLineSize code, which breaks the registers + * down into their component descriptors. In the end the lineSize of the + * lowest level cache data cache is returned. */ + cpuid(2, &eax, &ebx, &ecx, &edx); + repeat = eax & 0xf; + for (count = 0; count < repeat; count++) { + if ((eax & 0x80000000) == 0) { + getIntelRegisterCacheLineSize(eax & 0xffffff00, &level, &lineSize); + } + if ((ebx & 0x80000000) == 0) { + getIntelRegisterCacheLineSize(ebx, &level, &lineSize); + } + if ((ecx & 0x80000000) == 0) { + getIntelRegisterCacheLineSize(ecx, &level, &lineSize); + } + if ((edx & 0x80000000) == 0) { + getIntelRegisterCacheLineSize(edx, &level, &lineSize); + } + if (count+1 != repeat) { + cpuid(2, &eax, &ebx, &ecx, &edx); + } + } + return lineSize; +} + +/* + * returns '0' if the cache info is not supported by this processor. + * This is based on the AMD extended cache commands for cpuid. + * (see "AMD Processor Recognition Application Note" Publication 20734). + * Some other processors use the identical scheme. + * (see "Processor Recognition, Transmeta Corporation"). + */ +static unsigned long +getOtherCacheLineSize(unsigned long cpuidLevel) +{ + unsigned long lineSize = 0; + unsigned long eax, ebx, ecx, edx; + + /* get the Extended CPUID level */ + cpuid(0x80000000, &eax, &ebx, &ecx, &edx); + cpuidLevel = eax; + + if (cpuidLevel >= 0x80000005) { + cpuid(0x80000005, &eax, &ebx, &ecx, &edx); + lineSize = ecx & 0xff; /* line Size, L1 Data Cache */ + } + return lineSize; +} + +static const char * const manMap[] = { +#define INTEL 0 + "GenuineIntel", +#define AMD 1 + "AuthenticAMD", +#define CYRIX 2 + "CyrixInstead", +#define CENTAUR 2 + "CentaurHauls", +#define NEXGEN 3 + "NexGenDriven", +#define TRANSMETA 4 + "GenuineTMx86", +#define RISE 5 + "RiseRiseRise", +#define UMC 6 + "UMC UMC UMC ", +#define SIS 7 + "Sis Sis Sis ", +#define NATIONAL 8 + "Geode by NSC", +}; + +static const int n_manufacturers = sizeof(manMap)/sizeof(manMap[0]); + +#define MAN_UNKNOWN 9 + + +unsigned long +s_mpi_getProcessorLineSize() +{ + unsigned long eax, ebx, ecx, edx; + unsigned long cpuidLevel; + unsigned long cacheLineSize = 0; + int manufacturer = MAN_UNKNOWN; + int i; + char string[65]; + +#if !defined(AMD_64) + if (is386()) { + return 0; /* 386 had no cache */ + } if (is486()) { + return 32; /* really? need more info */ + } +#endif + + /* Pentium, cpuid command is available */ + cpuid(0, &eax, &ebx, &ecx, &edx); + cpuidLevel = eax; + *(int *)string = ebx; + *(int *)&string[4] = edx; + *(int *)&string[8] = ecx; + string[12] = 0; + + manufacturer = MAN_UNKNOWN; + for (i=0; i < n_manufacturers; i++) { + if ( strcmp(manMap[i],string) == 0) { + manufacturer = i; + } + } + + if (manufacturer == INTEL) { + cacheLineSize = getIntelCacheLineSize(cpuidLevel); + } else { + cacheLineSize = getOtherCacheLineSize(cpuidLevel); + } + /* doesn't support cache info based on cpuid. This means + * an old pentium class processor, which have cache lines of + * 32. If we learn differently, we can use a switch based on + * the Manufacturer id */ + if (cacheLineSize == 0) { + cacheLineSize = 32; + } + return cacheLineSize; +} +#define MPI_GET_PROCESSOR_LINE_SIZE_DEFINED 1 +#endif + +#if defined(__ppc64__) +/* + * Sigh, The PPC has some really nice features to help us determine cache + * size, since it had lots of direct control functions to do so. The POWER + * processor even has an instruction to do this, but it was dropped in + * PowerPC. Unfortunately most of them are not available in user mode. + * + * The dcbz function would be a great way to determine cache line size except + * 1) it only works on write-back memory (it throws an exception otherwise), + * and 2) because so many mac programs 'knew' the processor cache size was + * 32 bytes, they used this instruction as a fast 'zero 32 bytes'. Now the new + * G5 processor has 128 byte cache, but dcbz only clears 32 bytes to keep + * these programs happy. dcbzl work if 64 bit instructions are supported. + * If you know 64 bit instructions are supported, and that stack is + * write-back, you can use this code. + */ +#include "memory.h" + +/* clear the cache line that contains 'array' */ +static inline void dcbzl(char *array) +{ + register char *a asm("r2") = array; + __asm__ __volatile__( "dcbzl %0,r0" : "=r" (a): "0"(a) ); +} + + +#define PPC_DO_ALIGN(x,y) ((char *)\ + ((((long long) (x))+((y)-1))&~((y)-1))) + +#define PPC_MAX_LINE_SIZE 256 +unsigned long +s_mpi_getProcessorLineSize() +{ + char testArray[2*PPC_MAX_LINE_SIZE+1]; + char *test; + int i; + + /* align the array on a maximum line size boundary, so we + * know we are starting to clear from the first address */ + test = PPC_DO_ALIGN(testArray, PPC_MAX_LINE_SIZE); + /* set all the values to 1's */ + memset(test, 0xff, PPC_MAX_LINE_SIZE); + /* clear one cache block starting at 'test' */ + dcbzl(test); + + /* find the size of the cleared area, that's our block size */ + for (i=PPC_MAX_LINE_SIZE; i != 0; i = i/2) { + if (test[i-1] == 0) { + return i; + } + } + return 0; +} + +#define MPI_GET_PROCESSOR_LINE_SIZE_DEFINED 1 +#endif + + +/* + * put other processor and platform specific cache code here + * return the smallest cache line size in bytes on the processor + * (usually the L1 cache). If the OS has a call, this would be + * a greate place to put it. + * + * If there is no cache, return 0; + * + * define MPI_GET_PROCESSOR_LINE_SIZE_DEFINED so the generic functions + * below aren't compiled. + * + */ + + +/* target.mk can define MPI_CACHE_LINE_SIZE if it's common for the family or + * OS */ +#if defined(MPI_CACHE_LINE_SIZE) && !defined(MPI_GET_PROCESSOR_LINE_SIZE_DEFINED) + +unsigned long +s_mpi_getProcessorLineSize() +{ + return MPI_CACHE_LINE_SIZE; +} +#define MPI_GET_PROCESSOR_LINE_SIZE_DEFINED 1 +#endif + + +/* If no way to get the processor cache line size has been defined, assume + * it's 32 bytes (most common value, does not significantly impact performance) + */ +#ifndef MPI_GET_PROCESSOR_LINE_SIZE_DEFINED +unsigned long +s_mpi_getProcessorLineSize() +{ + return 32; +} +#endif + +#ifdef TEST_IT +#include <stdio.h> + +main() +{ + printf("line size = %d\n", s_mpi_getProcessorLineSize()); +} +#endif diff --git a/security/nss/lib/freebl/mpi/mpcpucache_amd64.s b/security/nss/lib/freebl/mpi/mpcpucache_amd64.s new file mode 100644 index 000000000..240568475 --- /dev/null +++ b/security/nss/lib/freebl/mpi/mpcpucache_amd64.s @@ -0,0 +1,891 @@ +//* ***** BEGIN LICENSE BLOCK ***** +/ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 +/ * +/ * The contents of this file are subject to the Mozilla Public License Version +/ * 1.1 (the "License"); you may not use this file except in compliance with +/ * the License. You may obtain a copy of the License at +/ * http://www.mozilla.org/MPL/ +/ * +/ * Software distributed under the License is distributed on an "AS IS" basis, +/ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +/ * for the specific language governing rights and limitations under the +/ * License. +/ * +/ * The Initial Developer of the Original Code is +/ * Red Hat, Inc. +/ * Portions created by the Initial Developer are Copyright (C) 2005 +/ * the Initial Developer. All Rights Reserved. +/ * +/ * Contributor(s): +/ * Robert Relyea <rrelyea@redhat.com> +/ * +/ * Alternatively, the contents of this file may be used under the terms of +/ * either the GNU General Public License Version 2 or later (the "GPL"), or +/ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +/ * in which case the provisions of the GPL or the LGPL are applicable instead +/ * of those above. If you wish to allow use of your version of this file only +/ * under the terms of either the GPL or the LGPL, and not to allow others to +/ * use your version of this file under the terms of the MPL, indicate your +/ * decision by deleting the provisions above and replace them with the notice +/ * and other provisions required by the GPL or the LGPL. If you do not delete +/ * the provisions above, a recipient may use your version of this file under +/ * the terms of any one of the MPL, the GPL or the LGPL. +/ * +/ * ***** END LICENSE BLOCK ***** */ + + .file "mpcpucache.c" +/ .section .rodata.str1.1,"aMS",@progbits,1 + .section .rodata +.LC0: + .string "GenuineIntel" +.LC1: + .string "AuthenticAMD" +.LC2: + .string "CyrixInstead" +.LC3: + .string "CentaurHauls" +.LC4: + .string "NexGenDriven" +.LC5: + .string "GenuineTMx86" +.LC6: + .string "RiseRiseRise" +.LC7: + .string "UMC UMC UMC " +.LC8: + .string "Sis Sis Sis " +.LC9: + .string "Geode by NSC" + .section .data.rel.ro.local,"aw",@progbits + .align 32 + .type manMap, @object + .size manMap, 80 +manMap: + .quad .LC0 + .quad .LC1 + .quad .LC2 + .quad .LC3 + .quad .LC4 + .quad .LC5 + .quad .LC6 + .quad .LC7 + .quad .LC8 + .quad .LC9 + .section .rodata + .align 32 + .type CacheMap, @object + .size CacheMap, 512 +CacheMap: + .byte 0 + .byte 0 + .byte 3 + .byte 0 + .byte 3 + .byte 0 + .byte 4 + .byte 0 + .byte 4 + .zero 1 + .byte 1 + .byte 0 + .byte 7 + .byte 32 + .byte 1 + .byte 0 + .byte 7 + .byte 32 + .byte 1 + .byte 0 + .byte 8 + .byte 32 + .byte 1 + .byte 0 + .byte 8 + .byte 32 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 12 + .byte 64 + .byte 12 + .byte 64 + .byte 1 + .byte 0 + .byte 12 + .byte 64 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 12 + .byte 64 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 8 + .byte 64 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 7 + .byte 64 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 9 + .byte 64 + .byte 1 + .byte 0 + .byte 9 + .byte 64 + .byte 9 + .byte 64 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 9 + .byte 0 + .byte 9 + .byte 32 + .byte 9 + .byte 32 + .byte 9 + .byte 32 + .byte 9 + .byte 32 + .byte 9 + .byte 32 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 3 + .byte 0 + .byte 3 + .byte 0 + .byte 3 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 4 + .byte 0 + .byte 4 + .byte 0 + .byte 4 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 8 + .byte 64 + .byte 8 + .byte 64 + .byte 8 + .byte 64 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 5 + .byte 1 + .byte 5 + .byte 1 + .byte 5 + .byte 1 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 9 + .byte 64 + .byte 9 + .byte 64 + .byte 9 + .byte 64 + .byte 9 + .byte 64 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 9 + .byte 32 + .byte 9 + .byte 32 + .byte 9 + .byte 32 + .byte 9 + .byte 32 + .byte 9 + .byte 64 + .byte 9 + .byte 64 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 3 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 4 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .text + .align 16 + .type cpuid, @function +cpuid: +.LFB2: + movq %rdx, %r10 + pushq %rbx +.LCFI0: + movq %rcx, %r11 + movq %rdi, %rax +/APP + cpuid + +/NO_APP + movq %rax, (%rsi) + movq %rbx, (%r10) + popq %rbx + movq %rcx, (%r11) + movq %rdx, (%r8) + ret +.LFE2: + .size cpuid, .-cpuid + .align 16 + .type getIntelCacheEntryLineSize, @function +getIntelCacheEntryLineSize: +.LFB3: + leaq CacheMap(%rip), %r9 + movq %rdx, %r10 + movzbl 1(%r9,%rdi,2), %ecx + movzbl (%r9,%rdi,2), %r8d + testb %cl, %cl + je .L2 + cmpl $6, %r8d + sete %dl + cmpl $8, %r8d + sete %al + orl %edx, %eax + testb $1, %al + je .L4 + movl $1, (%rsi) +.L9: + movzbl %cl, %eax + movq %rax, (%r10) + ret + .align 16 +.L4: + movl (%rsi), %r11d + cmpl $1, %r11d + jg .L11 +.L6: + cmpl $2, %r11d + jle .L2 + cmpl $12, %r8d + sete %dl + cmpl $14, %r8d + sete %al + orl %edx, %eax + testb $1, %al + je .L2 + movzbq 1(%r9,%rdi,2), %rax + movl $3, (%rsi) + movq %rax, (%r10) + .align 16 +.L2: + rep ; ret + .align 16 +.L11: + cmpl $9, %r8d + sete %dl + cmpl $11, %r8d + sete %al + orl %edx, %eax + testb $1, %al + je .L6 + movl $2, (%rsi) + jmp .L9 +.LFE3: + .size getIntelCacheEntryLineSize, .-getIntelCacheEntryLineSize + .align 16 + .type getIntelRegisterCacheLineSize, @function +getIntelRegisterCacheLineSize: +.LFB4: + pushq %rbp +.LCFI1: + movq %rsp, %rbp +.LCFI2: + movq %rbx, -24(%rbp) +.LCFI3: + movq %rdi, %rbx + shrq $24, %rdi + movq %r12, -16(%rbp) +.LCFI4: + movq %r13, -8(%rbp) +.LCFI5: + andl $255, %edi + subq $24, %rsp +.LCFI6: + movq %rsi, %r13 + movq %rdx, %r12 + call getIntelCacheEntryLineSize + movq %rbx, %rdi + movq %r12, %rdx + movq %r13, %rsi + shrq $16, %rdi + andl $255, %edi + call getIntelCacheEntryLineSize + movq %rbx, %rdi + movq %r12, %rdx + movq %r13, %rsi + shrq $8, %rdi + andl $255, %ebx + andl $255, %edi + call getIntelCacheEntryLineSize + movq %r12, %rdx + movq %r13, %rsi + movq %rbx, %rdi + movq 8(%rsp), %r12 + movq (%rsp), %rbx + movq 16(%rsp), %r13 + leave + jmp getIntelCacheEntryLineSize +.LFE4: + .size getIntelRegisterCacheLineSize, .-getIntelRegisterCacheLineSize + .align 16 +.globl s_mpi_getProcessorLineSize + .type s_mpi_getProcessorLineSize, @function +s_mpi_getProcessorLineSize: +.LFB7: + pushq %rbp +.LCFI7: + xorl %edi, %edi + movq %rsp, %rbp +.LCFI8: + pushq %r15 +.LCFI9: + leaq -136(%rbp), %r8 + leaq -144(%rbp), %rcx + leaq -152(%rbp), %rdx + pushq %r14 +.LCFI10: + leaq -160(%rbp), %rsi + leaq -128(%rbp), %r14 + pushq %r13 +.LCFI11: + leaq manMap(%rip), %r13 + pushq %r12 +.LCFI12: + movl $9, %r12d + pushq %rbx +.LCFI13: + xorl %ebx, %ebx + subq $200, %rsp +.LCFI14: + call cpuid + movq -152(%rbp), %rax + movq -160(%rbp), %r15 + movb $0, -116(%rbp) + movl %eax, -128(%rbp) + movq -136(%rbp), %rax + movl %eax, -124(%rbp) + movq -144(%rbp), %rax + movl %eax, -120(%rbp) + .align 16 +.L18: + movslq %ebx,%rax + movq %r14, %rsi + movq (%r13,%rax,8), %rdi + call strcmp@PLT + testl %eax, %eax + cmove %ebx, %r12d + incl %ebx + cmpl $9, %ebx + jle .L18 + testl %r12d, %r12d + jne .L19 + xorl %eax, %eax + decl %r15d + movl $4, -204(%rbp) + movq $0, -200(%rbp) + jle .L21 + leaq -168(%rbp), %r8 + leaq -176(%rbp), %rcx + leaq -184(%rbp), %rdx + leaq -192(%rbp), %rsi + movl $2, %edi + xorl %ebx, %ebx + call cpuid + movq -192(%rbp), %rdi + movl %edi, %r12d + andl $15, %r12d + cmpl %r12d, %ebx + jl .L30 + jmp .L38 + .align 16 +.L25: + movq -184(%rbp), %rdi + testl $2147483648, %edi + je .L40 +.L26: + movq -176(%rbp), %rdi + testl $2147483648, %edi + je .L41 +.L27: + movq -168(%rbp), %rdi + testl $2147483648, %edi + je .L42 +.L28: + incl %ebx + cmpl %r12d, %ebx + je .L24 + leaq -168(%rbp), %r8 + leaq -176(%rbp), %rcx + leaq -184(%rbp), %rdx + leaq -192(%rbp), %rsi + movl $2, %edi + call cpuid +.L24: + cmpl %r12d, %ebx + jge .L38 + movq -192(%rbp), %rdi +.L30: + testl $2147483648, %edi + jne .L25 + leaq -200(%rbp), %rdx + leaq -204(%rbp), %rsi + andl $4294967040, %edi + call getIntelRegisterCacheLineSize + movq -184(%rbp), %rdi + testl $2147483648, %edi + jne .L26 +.L40: + leaq -200(%rbp), %rdx + leaq -204(%rbp), %rsi + call getIntelRegisterCacheLineSize + movq -176(%rbp), %rdi + testl $2147483648, %edi + jne .L27 +.L41: + leaq -200(%rbp), %rdx + leaq -204(%rbp), %rsi + call getIntelRegisterCacheLineSize + movq -168(%rbp), %rdi + testl $2147483648, %edi + jne .L28 +.L42: + leaq -200(%rbp), %rdx + leaq -204(%rbp), %rsi + call getIntelRegisterCacheLineSize + jmp .L28 +.L38: + movq -200(%rbp), %rax +.L21: + movq %rax, %rdx + movl $32, %eax + testq %rdx, %rdx + cmoveq %rax, %rdx + addq $200, %rsp + popq %rbx + popq %r12 + popq %r13 + popq %r14 + popq %r15 + leave + movq %rdx, %rax + ret +.L19: + leaq -216(%rbp), %r8 + leaq -224(%rbp), %rcx + leaq -232(%rbp), %rdx + leaq -240(%rbp), %rsi + movl $2147483648, %edi + xorl %ebx, %ebx + call cpuid + movl $2147483652, %eax + cmpq %rax, -240(%rbp) + ja .L43 +.L32: + movq %rbx, %rdx + movl $32, %eax + testq %rdx, %rdx + cmoveq %rax, %rdx + addq $200, %rsp + popq %rbx + popq %r12 + popq %r13 + popq %r14 + popq %r15 + leave + movq %rdx, %rax + ret +.L43: + leaq -216(%rbp), %r8 + leaq -224(%rbp), %rcx + leaq -232(%rbp), %rdx + leaq -240(%rbp), %rsi + movl $2147483653, %edi + call cpuid + movzbq -224(%rbp), %rbx + jmp .L32 +.LFE7: + .size s_mpi_getProcessorLineSize, .-s_mpi_getProcessorLineSize diff --git a/security/nss/lib/freebl/mpi/mpcpucache_x86.s b/security/nss/lib/freebl/mpi/mpcpucache_x86.s new file mode 100644 index 000000000..4e7813993 --- /dev/null +++ b/security/nss/lib/freebl/mpi/mpcpucache_x86.s @@ -0,0 +1,931 @@ +//* ***** BEGIN LICENSE BLOCK ***** +/ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 +/ * +/ * The contents of this file are subject to the Mozilla Public License Version +/ * 1.1 (the "License"); you may not use this file except in compliance with +/ * the License. You may obtain a copy of the License at +/ * http://www.mozilla.org/MPL/ +/ * +/ * Software distributed under the License is distributed on an "AS IS" basis, +/ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +/ * for the specific language governing rights and limitations under the +/ * License. +/ * +/ * The Initial Developer of the Original Code is +/ * Red Hat, Inc. +/ * Portions created by the Initial Developer are Copyright (C) 2005 +/ * the Initial Developer. All Rights Reserved. +/ * +/ * Contributor(s): +/ * Robert Relyea <rrelyea@redhat.com> +/ * +/ * Alternatively, the contents of this file may be used under the terms of +/ * either the GNU General Public License Version 2 or later (the "GPL"), or +/ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +/ * in which case the provisions of the GPL or the LGPL are applicable instead +/ * of those above. If you wish to allow use of your version of this file only +/ * under the terms of either the GPL or the LGPL, and not to allow others to +/ * use your version of this file under the terms of the MPL, indicate your +/ * decision by deleting the provisions above and replace them with the notice +/ * and other provisions required by the GPL or the LGPL. If you do not delete +/ * the provisions above, a recipient may use your version of this file under +/ * the terms of any one of the MPL, the GPL or the LGPL. +/ * +/ * ***** END LICENSE BLOCK ***** */ + + .file "mpcpucache.c" +/ .section .rodata.str1.1,"aMS",@progbits,1 + .section .rodata +.LC0: + .string "GenuineIntel" +.LC1: + .string "AuthenticAMD" +.LC2: + .string "CyrixInstead" +.LC3: + .string "CentaurHauls" +.LC4: + .string "NexGenDriven" +.LC5: + .string "GenuineTMx86" +.LC6: + .string "RiseRiseRise" +.LC7: + .string "UMC UMC UMC " +.LC8: + .string "Sis Sis Sis " +.LC9: + .string "Geode by NSC" + .section .data.rel.ro.local,"aw",@progbits + .align 32 + .type manMap, @object + .size manMap, 40 +manMap: + .long .LC0 + .long .LC1 + .long .LC2 + .long .LC3 + .long .LC4 + .long .LC5 + .long .LC6 + .long .LC7 + .long .LC8 + .long .LC9 + .section .rodata + .align 32 + .type CacheMap, @object + .size CacheMap, 512 +CacheMap: + .byte 0 + .byte 0 + .byte 3 + .byte 0 + .byte 3 + .byte 0 + .byte 4 + .byte 0 + .byte 4 + .zero 1 + .byte 1 + .byte 0 + .byte 7 + .byte 32 + .byte 1 + .byte 0 + .byte 7 + .byte 32 + .byte 1 + .byte 0 + .byte 8 + .byte 32 + .byte 1 + .byte 0 + .byte 8 + .byte 32 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 12 + .byte 64 + .byte 12 + .byte 64 + .byte 1 + .byte 0 + .byte 12 + .byte 64 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 12 + .byte 64 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 8 + .byte 64 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 7 + .byte 64 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 9 + .byte 64 + .byte 1 + .byte 0 + .byte 9 + .byte 64 + .byte 9 + .byte 64 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 9 + .byte 0 + .byte 9 + .byte 32 + .byte 9 + .byte 32 + .byte 9 + .byte 32 + .byte 9 + .byte 32 + .byte 9 + .byte 32 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 3 + .byte 0 + .byte 3 + .byte 0 + .byte 3 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 4 + .byte 0 + .byte 4 + .byte 0 + .byte 4 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 8 + .byte 64 + .byte 8 + .byte 64 + .byte 8 + .byte 64 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 5 + .byte 1 + .byte 5 + .byte 1 + .byte 5 + .byte 1 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 9 + .byte 64 + .byte 9 + .byte 64 + .byte 9 + .byte 64 + .byte 9 + .byte 64 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 9 + .byte 32 + .byte 9 + .byte 32 + .byte 9 + .byte 32 + .byte 9 + .byte 32 + .byte 9 + .byte 64 + .byte 9 + .byte 64 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 3 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 4 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .byte 1 + .byte 0 + .text + .align 4 + .type cpuid, @function +cpuid: + pushl %ebp + pushl %edi + pushl %esi + subl $8, %esp + movl %edx, %ebp +/APP + pushl %ebx + cpuid + mov %ebx,%esi + popl %ebx + +/NO_APP + movl %eax, (%ebp) + movl 24(%esp), %eax + movl %esi, (%eax) + movl 28(%esp), %eax + movl %ecx, (%eax) + movl 32(%esp), %eax + movl %edx, (%eax) + addl $8, %esp + popl %esi + popl %edi + popl %ebp + ret + .size cpuid, .-cpuid + .align 4 + .type changeFlag, @function +changeFlag: +/APP + pushfl + popl %edx + movl %edx,%ecx + xorl %eax,%edx + pushl %edx + popfl + pushfl + popl %edx + pushl %ecx + popfl + +/NO_APP + xorl %ecx, %edx + movl %edx, %eax + ret + .size changeFlag, .-changeFlag + .align 4 + .type getIntelCacheEntryLineSize, @function +getIntelCacheEntryLineSize: + pushl %edi + pushl %esi + pushl %ebx + call .L17 +.L17: + popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-.L17], %ebx + movzbl CacheMap@GOTOFF(%ebx,%eax,2), %ecx + movb 1+CacheMap@GOTOFF(%ebx,%eax,2), %al + testb %al, %al + movl 16(%esp), %edi + je .L3 + cmpl $6, %ecx + je .L6 + cmpl $8, %ecx + je .L6 + movl (%edx), %esi + cmpl $1, %esi + jg .L15 +.L8: + cmpl $2, %esi + jle .L3 + cmpl $12, %ecx + je .L12 + cmpl $14, %ecx + je .L12 + .align 4 +.L3: + popl %ebx + popl %esi + popl %edi + ret + .align 4 +.L6: + movzbl %al, %eax + movl $1, (%edx) + movl %eax, (%edi) +.L16: + popl %ebx + popl %esi + popl %edi + ret + .align 4 +.L15: + cmpl $9, %ecx + je .L9 + cmpl $11, %ecx + jne .L8 +.L9: + movzbl %al, %eax + movl $2, (%edx) + movl %eax, (%edi) + jmp .L16 +.L12: + movzbl %al, %eax + movl $3, (%edx) + movl %eax, (%edi) + jmp .L16 + .size getIntelCacheEntryLineSize, .-getIntelCacheEntryLineSize + .align 4 + .type getIntelRegisterCacheLineSize, @function +getIntelRegisterCacheLineSize: + pushl %ebp + movl %esp, %ebp + pushl %edi + pushl %esi + pushl %ecx + movl 8(%ebp), %edi + movl %eax, %esi + movl %edx, -12(%ebp) + shrl $24, %eax + pushl %edi + call getIntelCacheEntryLineSize + movl %esi, %eax + pushl %edi + shrl $16, %eax + movl -12(%ebp), %edx + andl $255, %eax + call getIntelCacheEntryLineSize + pushl %edi + movl %esi, %edx + movzbl %dh, %eax + movl -12(%ebp), %edx + call getIntelCacheEntryLineSize + andl $255, %esi + movl %edi, 8(%ebp) + movl -12(%ebp), %edx + addl $12, %esp + leal -8(%ebp), %esp + movl %esi, %eax + popl %esi + popl %edi + leave + jmp getIntelCacheEntryLineSize + .size getIntelRegisterCacheLineSize, .-getIntelRegisterCacheLineSize + .align 4 +.globl s_mpi_getProcessorLineSize + .type s_mpi_getProcessorLineSize, @function +s_mpi_getProcessorLineSize: + pushl %ebp + movl %esp, %ebp + pushl %edi + pushl %esi + pushl %ebx + subl $188, %esp + call .L52 +.L52: + popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-.L52], %ebx + movl $9, -168(%ebp) + movl $262144, %eax + call changeFlag + xorl %edx, %edx + testl %eax, %eax + jne .L50 +.L19: + leal -12(%ebp), %esp + popl %ebx + popl %esi + movl %edx, %eax + popl %edi + leave + ret + .align 4 +.L50: + movl $2097152, %eax + call changeFlag + testl %eax, %eax + movl $32, %edx + je .L19 + leal -108(%ebp), %eax + pushl %eax + leal -112(%ebp), %eax + pushl %eax + leal -116(%ebp), %eax + pushl %eax + leal -120(%ebp), %edx + xorl %eax, %eax + call cpuid + movl -120(%ebp), %eax + movl %eax, -164(%ebp) + movl -116(%ebp), %eax + movl %eax, -104(%ebp) + movl -108(%ebp), %eax + movl %eax, -100(%ebp) + movl -112(%ebp), %eax + movl %eax, -96(%ebp) + movb $0, -92(%ebp) + xorl %esi, %esi + addl $12, %esp + leal -104(%ebp), %edi + .align 4 +.L28: + subl $8, %esp + pushl %edi + pushl manMap@GOTOFF(%ebx,%esi,4) + call strcmp@PLT + addl $16, %esp + testl %eax, %eax + jne .L26 + movl %esi, -168(%ebp) +.L26: + incl %esi + cmpl $9, %esi + jle .L28 + movl -168(%ebp), %eax + testl %eax, %eax + jne .L29 + xorl %eax, %eax + cmpl $1, -164(%ebp) + movl $4, -144(%ebp) + movl $0, -140(%ebp) + jle .L41 + leal -124(%ebp), %edx + movl %edx, -188(%ebp) + leal -128(%ebp), %eax + pushl %edx + movl %eax, -184(%ebp) + leal -132(%ebp), %edx + pushl %eax + movl %edx, -180(%ebp) + movl $2, %eax + pushl %edx + leal -136(%ebp), %edx + call cpuid + movl -136(%ebp), %eax + movl %eax, %edi + andl $15, %edi + xorl %esi, %esi + addl $12, %esp + leal -140(%ebp), %edx + cmpl %edi, %esi + movl %edx, -176(%ebp) + jl .L40 + jmp .L48 + .align 4 +.L49: + movl -136(%ebp), %eax +.L40: + testl %eax, %eax + js .L35 + xorb %al, %al + pushl -176(%ebp) + leal -144(%ebp), %edx + call getIntelRegisterCacheLineSize + popl %eax +.L35: + movl -132(%ebp), %eax + testl %eax, %eax + js .L36 + pushl -176(%ebp) + leal -144(%ebp), %edx + call getIntelRegisterCacheLineSize + popl %eax +.L36: + movl -128(%ebp), %eax + testl %eax, %eax + js .L37 + pushl -176(%ebp) + leal -144(%ebp), %edx + call getIntelRegisterCacheLineSize + popl %eax +.L37: + movl -124(%ebp), %eax + testl %eax, %eax + js .L38 + pushl -176(%ebp) + leal -144(%ebp), %edx + call getIntelRegisterCacheLineSize + popl %eax +.L38: + incl %esi + cmpl %edi, %esi + je .L34 + pushl -188(%ebp) + pushl -184(%ebp) + pushl -180(%ebp) + leal -136(%ebp), %edx + movl $2, %eax + call cpuid + addl $12, %esp +.L34: + cmpl %edi, %esi + jl .L49 +.L48: + movl -140(%ebp), %eax +.L41: + testl %eax, %eax + jne .L44 + movb $32, %al +.L44: + leal -12(%ebp), %esp + popl %ebx + popl %esi + movl %eax, %edx + movl %edx, %eax + popl %edi + leave + ret +.L29: + leal -148(%ebp), %eax + movl %eax, -192(%ebp) + movl $0, -172(%ebp) + leal -152(%ebp), %edi + pushl %eax + pushl %edi + leal -156(%ebp), %esi + pushl %esi + leal -160(%ebp), %edx + movl $-2147483648, %eax + call cpuid + addl $12, %esp + cmpl $-2147483644, -160(%ebp) + ja .L51 +.L42: + movl -172(%ebp), %eax + jmp .L41 +.L51: + pushl -192(%ebp) + pushl %edi + pushl %esi + leal -160(%ebp), %edx + movl $-2147483643, %eax + call cpuid + movzbl -152(%ebp), %edx + addl $12, %esp + movl %edx, -172(%ebp) + jmp .L42 + .size s_mpi_getProcessorLineSize, .-s_mpi_getProcessorLineSize diff --git a/security/nss/lib/freebl/mpi/mpi-priv.h b/security/nss/lib/freebl/mpi/mpi-priv.h index 69f3c1aa9..e033a5e24 100644 --- a/security/nss/lib/freebl/mpi/mpi-priv.h +++ b/security/nss/lib/freebl/mpi/mpi-priv.h @@ -231,6 +231,22 @@ mp_err s_mp_invmod_odd_m( const mp_int *a, const mp_int *m, mp_int *c); mp_err s_mp_invmod_2d( const mp_int *a, mp_size k, mp_int *c); mp_err s_mp_invmod_even_m(const mp_int *a, const mp_int *m, mp_int *c); +#ifdef NSS_USE_COMBA + +#define IS_POWER_OF_2(a) ((a) && !((a) & ((a)-1))) + +void s_mp_mul_comba_4(const mp_int *A, const mp_int *B, mp_int *C); +void s_mp_mul_comba_8(const mp_int *A, const mp_int *B, mp_int *C); +void s_mp_mul_comba_16(const mp_int *A, const mp_int *B, mp_int *C); +void s_mp_mul_comba_32(const mp_int *A, const mp_int *B, mp_int *C); + +void s_mp_sqr_comba_4(const mp_int *A, mp_int *B); +void s_mp_sqr_comba_8(const mp_int *A, mp_int *B); +void s_mp_sqr_comba_16(const mp_int *A, mp_int *B); +void s_mp_sqr_comba_32(const mp_int *A, mp_int *B); + +#endif /* end NSS_USE_COMBA */ + /* ------ mpv functions, operate on arrays of digits, not on mp_int's ------ */ #if defined (__OS2__) && defined (__IBMC__) #define MPI_ASM_DECL __cdecl @@ -284,6 +300,19 @@ mp_err s_mp_mul_mont(const mp_int *a, const mp_int *b, mp_int *c, mp_mont_modulus *mmm); mp_err s_mp_redc(mp_int *T, mp_mont_modulus *mmm); +/* + * s_mpi_getProcessorLineSize() returns the size in bytes of the cache line + * if a cache exists, or zero if there is no cache. If more than one + * cache line exists, it should return the smallest line size (which is + * usually the L1 cache). + * + * mp_modexp uses this information to make sure that private key information + * isn't being leaked through the cache. + * + * see mpcpucache.c for the implementation. + */ +unsigned long s_mpi_getProcessorLineSize(); + /* }}} */ #endif diff --git a/security/nss/lib/freebl/mpi/mpi.c b/security/nss/lib/freebl/mpi/mpi.c index 4caa6d224..2ea3ad15e 100644 --- a/security/nss/lib/freebl/mpi/mpi.c +++ b/security/nss/lib/freebl/mpi/mpi.c @@ -844,6 +844,27 @@ mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int * c) if((res = s_mp_pad(c, USED(a) + USED(b))) != MP_OKAY) goto CLEANUP; +#ifdef NSS_USE_COMBA + if ((MP_USED(a) == MP_USED(b)) && IS_POWER_OF_2(MP_USED(b))) { + if (MP_USED(a) == 4) { + s_mp_mul_comba_4(a, b, c); + goto CLEANUP; + } + if (MP_USED(a) == 8) { + s_mp_mul_comba_8(a, b, c); + goto CLEANUP; + } + if (MP_USED(a) == 16) { + s_mp_mul_comba_16(a, b, c); + goto CLEANUP; + } + if (MP_USED(a) == 32) { + s_mp_mul_comba_32(a, b, c); + goto CLEANUP; + } + } +#endif + pb = MP_DIGITS(b); s_mpv_mul_d(MP_DIGITS(a), MP_USED(a), *pb++, MP_DIGITS(c)); @@ -914,6 +935,27 @@ mp_err mp_sqr(const mp_int *a, mp_int *sqr) MP_USED(sqr) = ix; MP_DIGIT(sqr, 0) = 0; +#ifdef NSS_USE_COMBA + if (IS_POWER_OF_2(MP_USED(a))) { + if (MP_USED(a) == 4) { + s_mp_sqr_comba_4(a, sqr); + goto CLEANUP; + } + if (MP_USED(a) == 8) { + s_mp_sqr_comba_8(a, sqr); + goto CLEANUP; + } + if (MP_USED(a) == 16) { + s_mp_sqr_comba_16(a, sqr); + goto CLEANUP; + } + if (MP_USED(a) == 32) { + s_mp_sqr_comba_32(a, sqr); + goto CLEANUP; + } + } +#endif + pa = MP_DIGITS(a); count = MP_USED(a) - 1; if (count > 0) { @@ -4717,6 +4759,8 @@ mp_to_unsigned_octets(const mp_int *mp, unsigned char *str, mp_size maxlen) str[pos++] = x; } } + if (!pos) + str[pos++] = 0; return pos; } /* end mp_to_unsigned_octets() */ /* }}} */ @@ -4755,6 +4799,8 @@ mp_to_signed_octets(const mp_int *mp, unsigned char *str, mp_size maxlen) str[pos++] = x; } } + if (!pos) + str[pos++] = 0; return pos; } /* end mp_to_signed_octets() */ /* }}} */ @@ -4790,6 +4836,8 @@ mp_to_fixlen_octets(const mp_int *mp, unsigned char *str, mp_size length) str[pos++] = x; } } + if (!pos) + str[pos++] = 0; return MP_OKAY; } /* end mp_to_fixlen_octets() */ /* }}} */ diff --git a/security/nss/lib/freebl/mpi/mpi_amd64_gas.s b/security/nss/lib/freebl/mpi/mpi_amd64_gas.s index 7515ac20a..86e16e362 100644 --- a/security/nss/lib/freebl/mpi/mpi_amd64_gas.s +++ b/security/nss/lib/freebl/mpi/mpi_amd64_gas.s @@ -416,3 +416,7 @@ ret .size s_mpv_mul_add_vec64, [.-s_mpv_mul_add_vec64] + +# Magic indicating no need for an executable stack +.section .note.GNU-stack, "", @progbits +.previous diff --git a/security/nss/lib/freebl/mpi/mpmontg.c b/security/nss/lib/freebl/mpi/mpmontg.c index 8879454ae..7b0bdd3d3 100644 --- a/security/nss/lib/freebl/mpi/mpmontg.c +++ b/security/nss/lib/freebl/mpi/mpmontg.c @@ -47,7 +47,7 @@ * published by Springer Verlag. */ -/* #define MP_USING_MONT_MULF 1 */ +#define MP_USING_CACHE_SAFE_MOD_EXP 1 #include <string.h> #include "mpi-priv.h" #include "mplogic.h" @@ -55,11 +55,19 @@ #ifdef MP_USING_MONT_MULF #include "montmulf.h" #endif +#include <stddef.h> /* ptrdiff_t */ + +/* if MP_CHAR_STORE_SLOW is defined, we */ +/* need to know endianness of this platform. */ +#ifdef MP_CHAR_STORE_SLOW +#if !defined(MPI_IS_BIG_ENDIAN) && !defined(MPI_IS_LITTLE_ENDIAN) +#error "You must define MPI_IS_BIG_ENDIAN or MPI_IS_LITTLE_ENDIAN\n" \ + " if you define MP_CHAR_STORE_SLOW." +#endif +#endif #define STATIC -/* #define DEBUG 1 */ -#define MAX_WINDOW_BITS 6 #define MAX_ODD_INTS 32 /* 2 ** (WINDOW_BITS - 1) */ #if defined(_WIN32_WCE) @@ -174,6 +182,13 @@ CLEANUP: #ifdef MP_USING_MONT_MULF +/* the floating point multiply is already cache safe, + * don't turn on cache safe unless we specifically + * force it */ +#ifndef MP_FORCE_CACHE_SAFE +#undef MP_USING_CACHE_SAFE_MOD_EXP +#endif + unsigned int mp_using_mont_mulf = 1; /* computes montgomery square of the integer in mResult */ @@ -504,6 +519,564 @@ CLEANUP: #undef SQR #undef MUL +#ifdef MP_USING_CACHE_SAFE_MOD_EXP +unsigned int mp_using_cache_safe_exp = 1; +#endif + +mp_err mp_set_safe_modexp(int value) +{ +#ifdef MP_USING_CACHE_SAFE_MOD_EXP + mp_using_cache_safe_exp = value; + return MP_OKAY; +#else + if (value == 0) { + return MP_OKAY; + } + return MP_BADARG; +#endif +} + +#ifdef MP_USING_CACHE_SAFE_MOD_EXP +#define WEAVE_WORD_SIZE 4 + +#ifndef MP_CHAR_STORE_SLOW +/* + * mpi_to_weave takes MPI data and stores in into a byte array interleaved. + * + * The purpose of this interleaving is to hide our access to the array of + * modulus powers from and attacker snooping on cache hits and misses. Because + * the array is interleaved, each reference will cause exactly the same cache + * lines to reload. + * + * There are 2 different implementations in this file, one which works with just + * byte loads and stores, the second which works with mp_weave_word loads and + * stores. These 2 implementations have DIFFERENT results in exactly which byte + * of an mp_digit winds up in which location in the byte array. That is why + * there are 2 sets of explanations for how the array is set up. + * + * + * a is an array of WEAVE_WORD_SIZE mp_ints (that is 4). + * It is a partial window into a logical array mp_int p[count] containing + * the base to the 0 through count-1 powers. Ideally this code would be + * simpler if we stored one element of that array at a time, but on some + * platforms the cost of storing a byte incurs a full read modify write cycle + * and increases the memory bandwidth cost by a factor of 4 or 8. By collecting + * for mp_ints together, we can arrange to store all 4 values in a single + * word write. + * + * b is the targeted weaved location. b[0] points to the first byte where + * first byte of the a array needs to be stored. Each b is an offset into the + * weave array. + * + * count is 2^window size. + * + * b_size is the size in mp_digits of each mp_int in the array. mp_ints + * with less than b_size elements are logically padded with zeros before + * storing. + * + * + * Data is stored as follows : + * The mp_int array is treated as a byte array. + * + * + * we want to eventually store the logical array mp_int p[count] into the + * weave array as follows: + + * p[count].digit is treated as a byte array (rather than * an mp_digit array), + * N is count, and n is b_size * *sizeof(mp_digit): + * + * p[0].digit[0] p[1].digit[0] ...... p[N-2].digit[0] p[N-1].digit[0] + * p[0].digit[1] p[1].digit[1] ...... p[N-2].digit[1] p[N-1].digit[1] + * . . + * . . + * p[0].digit[n-2] p[1].digit[n-2] ...... p[N-2].digit[n-2] p[N-1].digit[n-2] + * p[0].digit[n-1] p[1].digit[n-1] ...... p[N-2].digit[n-1] p[N-1].digit[n-1] + * + * This function stores that a window of p in each call. + */ +mp_err mpi_to_weave(const mp_int *a, unsigned char *b, + mp_size b_size, mp_size count) +{ + mp_size i, j; + unsigned char *bsave = b; + + for (i=0; i < WEAVE_WORD_SIZE; i++) { + unsigned char *pb = (unsigned char *)MP_DIGITS(&a[i]); + mp_size useda = MP_USED(&a[i]); + mp_size zero = b_size - useda; + unsigned char *end = pb+ (useda*sizeof(mp_digit)); + b = bsave+i; + + + ARGCHK(MP_SIGN(&a[i]) == MP_ZPOS, MP_BADARG); + ARGCHK(useda <= b_size, MP_BADARG); + + for (; pb < end; pb++) { + *b = *pb; + b += count; + } + for (j=0; j < zero; j++) { + *b = 0; + b += count; + } + } + + return MP_OKAY; +} + +/* reverse the operation above for one entry. + * b points to the offset into the weave array of the power we are + * calculating */ +mp_err weave_to_mpi(mp_int *a, const unsigned char *b, + mp_size b_size, mp_size count) +{ + unsigned char *pb = (unsigned char *)MP_DIGITS(a); + unsigned char *end = pb+ (b_size*sizeof(mp_digit)); + + MP_SIGN(a) = MP_ZPOS; + MP_USED(a) = b_size; + + for (; pb < end; b+=count, pb++) { + *pb = *b; + } + s_mp_clamp(a); + return MP_OKAY; +} +#else +/* Need a primitive that we know is 32 bits long... */ +/* this is true on all modern processors we know of today*/ +typedef unsigned int mp_weave_word; + +/* + * on some platforms character stores into memory is very expensive since they + * generate a read/modify/write operation on the bus. On those platforms + * we need to do integer writes to the bus. Because of some unrolled code, + * in this current code the size of mp_weave_word must be four. The code that + * makes this assumption explicity is called out. (on some platforms a write + * of 4 bytes still requires a single read-modify-write operation. + * + * This function is takes the identical parameters as the function above, + * however it lays out the final array differently. Where the previous function + * treats the mpi_int as an byte array, this function treats it as an array of + * mp_digits where each digit is stored in big endian order. + * + * since we need to interleave on a byte by byte basis, we need to collect + * several mpi structures together into a single uint32 before we write. We + * also need to make sure the uint32 is arranged so that the first value of + * the first array winds up in b[0]. This means construction of that uint32 + * is endian specific (even though the layout of the mp_digits in the array + * is always big endian). + * + * The final data is stored as follows : + * + * Our same logical array p array, m is sizeof(mp_digit), + * N is still count and n is now b_size. If we define p[i].digit[j]0 as the + * most significant byte of the word p[i].digit[j], p[i].digit[j]1 as + * the next most significant byte of p[i].digit[j], ... and p[i].digit[j]m-1 + * is the least significant byte. + * Our array would look like: + * p[0].digit[0]0 p[1].digit[0]0 ... p[N-2].digit[0]0 p[N-1].digit[0]0 + * p[0].digit[0]1 p[1].digit[0]1 ... p[N-2].digit[0]1 p[N-1].digit[0]1 + * . . + * p[0].digit[0]m-1 p[1].digit[0]m-1 ... p[N-2].digit[0]m-1 p[N-1].digit[0]m-1 + * p[0].digit[1]0 p[1].digit[1]0 ... p[N-2].digit[1]0 p[N-1].digit[1]0 + * . . + * . . + * p[0].digit[n-1]m-2 p[1].digit[n-1]m-2 ... p[N-2].digit[n-1]m-2 p[N-1].digit[n-1]m-2 + * p[0].digit[n-1]m-1 p[1].digit[n-1]m-1 ... p[N-2].digit[n-1]m-1 p[N-1].digit[n-1]m-1 + * + */ +mp_err mpi_to_weave(const mp_int *a, unsigned char *b, + mp_size b_size, mp_size count) +{ + mp_size i; + mp_digit *digitsa0; + mp_digit *digitsa1; + mp_digit *digitsa2; + mp_digit *digitsa3; + mp_size useda0; + mp_size useda1; + mp_size useda2; + mp_size useda3; + mp_weave_word *weaved = (mp_weave_word *)b; + + count = count/sizeof(mp_weave_word); + + /* this code pretty much depends on this ! */ +#if MP_ARGCHK < 2 + assert(WEAVE_WORD_SIZE == 4); + assert(sizeof(mp_weave_word) == 4); +#endif + + digitsa0 = MP_DIGITS(&a[0]); + digitsa1 = MP_DIGITS(&a[1]); + digitsa2 = MP_DIGITS(&a[2]); + digitsa3 = MP_DIGITS(&a[3]); + useda0 = MP_USED(&a[0]); + useda1 = MP_USED(&a[1]); + useda2 = MP_USED(&a[2]); + useda3 = MP_USED(&a[3]); + + ARGCHK(MP_SIGN(&a[0]) == MP_ZPOS, MP_BADARG); + ARGCHK(MP_SIGN(&a[1]) == MP_ZPOS, MP_BADARG); + ARGCHK(MP_SIGN(&a[2]) == MP_ZPOS, MP_BADARG); + ARGCHK(MP_SIGN(&a[3]) == MP_ZPOS, MP_BADARG); + ARGCHK(useda0 <= b_size, MP_BADARG); + ARGCHK(useda1 <= b_size, MP_BADARG); + ARGCHK(useda2 <= b_size, MP_BADARG); + ARGCHK(useda3 <= b_size, MP_BADARG); + +#define SAFE_FETCH(digit, used, word) ((word) < (used) ? (digit[word]) : 0) + + for (i=0; i < b_size; i++) { + mp_digit d0 = SAFE_FETCH(digitsa0,useda0,i); + mp_digit d1 = SAFE_FETCH(digitsa1,useda1,i); + mp_digit d2 = SAFE_FETCH(digitsa2,useda2,i); + mp_digit d3 = SAFE_FETCH(digitsa3,useda3,i); + register mp_weave_word acc; + +/* + * ONE_STEP takes the MSB of each of our current digits and places that + * byte in the appropriate position for writing to the weaved array. + * On little endian: + * b3 b2 b1 b0 + * On big endian: + * b0 b1 b2 b3 + * When the data is written it would always wind up: + * b[0] = b0 + * b[1] = b1 + * b[2] = b2 + * b[3] = b3 + * + * Once we've written the MSB, we shift the whole digit up left one + * byte, putting the Next Most Significant Byte in the MSB position, + * so we we repeat the next one step that byte will be written. + * NOTE: This code assumes sizeof(mp_weave_word) and MP_WEAVE_WORD_SIZE + * is 4. + */ +#ifdef IS_LITTLE_ENDIAN +#define MPI_WEAVE_ONE_STEP \ + acc = (d0 >> (MP_DIGIT_BITS-8)) & 0x000000ff; d0 <<= 8; /*b0*/ \ + acc |= (d1 >> (MP_DIGIT_BITS-16)) & 0x0000ff00; d1 <<= 8; /*b1*/ \ + acc |= (d2 >> (MP_DIGIT_BITS-24)) & 0x00ff0000; d2 <<= 8; /*b2*/ \ + acc |= (d3 >> (MP_DIGIT_BITS-32)) & 0xff000000; d3 <<= 8; /*b3*/ \ + *weaved = acc; weaved += count; +#else +#define MPI_WEAVE_ONE_STEP \ + acc = (d0 >> (MP_DIGIT_BITS-32)) & 0xff000000; d0 <<= 8; /*b0*/ \ + acc |= (d1 >> (MP_DIGIT_BITS-24)) & 0x00ff0000; d1 <<= 8; /*b1*/ \ + acc |= (d2 >> (MP_DIGIT_BITS-16)) & 0x0000ff00; d2 <<= 8; /*b2*/ \ + acc |= (d3 >> (MP_DIGIT_BITS-8)) & 0x000000ff; d3 <<= 8; /*b3*/ \ + *weaved = acc; weaved += count; +#endif + switch (sizeof(mp_digit)) { + case 32: + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + case 16: + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + case 8: + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + case 4: + MPI_WEAVE_ONE_STEP + MPI_WEAVE_ONE_STEP + case 2: + MPI_WEAVE_ONE_STEP + case 1: + MPI_WEAVE_ONE_STEP + break; + } + } + + return MP_OKAY; +} + +/* reverse the operation above for one entry. + * b points to the offset into the weave array of the power we are + * calculating */ +mp_err weave_to_mpi(mp_int *a, const unsigned char *b, + mp_size b_size, mp_size count) +{ + mp_digit *pb = MP_DIGITS(a); + mp_digit *end = &pb[b_size]; + + MP_SIGN(a) = MP_ZPOS; + MP_USED(a) = b_size; + + for (; pb < end; pb++) { + register mp_digit digit; + + digit = *b << 8; b += count; +#define MPI_UNWEAVE_ONE_STEP digit |= *b; b += count; digit = digit << 8; + switch (sizeof(mp_digit)) { + case 32: + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + case 16: + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + case 8: + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + case 4: + MPI_UNWEAVE_ONE_STEP + MPI_UNWEAVE_ONE_STEP + case 2: + break; + } + digit |= *b; b += count; + + *pb = digit; + } + s_mp_clamp(a); + return MP_OKAY; +} +#endif + + +#define SQR(a,b) \ + MP_CHECKOK( mp_sqr(a, b) );\ + MP_CHECKOK( s_mp_redc(b, mmm) ) + +#if defined(MP_MONT_USE_MP_MUL) +#define MUL_NOWEAVE(x,a,b) \ + MP_CHECKOK( mp_mul(a, x, b) ); \ + MP_CHECKOK( s_mp_redc(b, mmm) ) +#else +#define MUL_NOWEAVE(x,a,b) \ + MP_CHECKOK( s_mp_mul_mont(a, x, b, mmm) ) +#endif + +#define MUL(x,a,b) \ + MP_CHECKOK( weave_to_mpi(&tmp, powers + (x), nLen, num_powers) ); \ + MUL_NOWEAVE(&tmp,a,b) + +#define SWAPPA ptmp = pa1; pa1 = pa2; pa2 = ptmp +#define MP_ALIGN(x,y) ((((ptrdiff_t)(x))+((y)-1))&(((ptrdiff_t)0)-(y))) + +/* Do modular exponentiation using integer multiply code. */ +mp_err mp_exptmod_safe_i(const mp_int * montBase, + const mp_int * exponent, + const mp_int * modulus, + mp_int * result, + mp_mont_modulus *mmm, + int nLen, + mp_size bits_in_exponent, + mp_size window_bits, + mp_size num_powers) +{ + mp_int *pa1, *pa2, *ptmp; + mp_size i; + mp_size first_window; + mp_err res; + int expOff; + mp_int accum1, accum2, accum[WEAVE_WORD_SIZE]; + mp_int tmp; + unsigned char *powersArray; + unsigned char *powers; + + powersArray = (unsigned char *)malloc(num_powers*(nLen*sizeof(mp_digit)+1)); + if (powersArray == NULL) { + res = MP_MEM; + goto CLEANUP; + } + + /* powers[i] = base ** (i); */ + powers = (unsigned char *)MP_ALIGN(powersArray,num_powers); + + MP_DIGITS(&accum1) = 0; + MP_DIGITS(&accum2) = 0; + MP_DIGITS(&accum[0]) = 0; + MP_DIGITS(&accum[1]) = 0; + MP_DIGITS(&accum[2]) = 0; + MP_DIGITS(&accum[3]) = 0; + + /* grab the first window value. This allows us to preload accumulator1 + * and save a conversion, some squares and a multiple*/ + MP_CHECKOK( mpl_get_bits(exponent, + bits_in_exponent-window_bits, window_bits) ); + first_window = (mp_size)res; + + MP_CHECKOK( mp_init_size(&accum1, 3 * nLen + 2) ); + MP_CHECKOK( mp_init_size(&accum2, 3 * nLen + 2) ); + MP_DIGITS(&tmp) = 0; + MP_CHECKOK( mp_init_size(&tmp, 3 * nLen + 2) ); + + /* build the first WEAVE_WORD powers inline */ + /* if WEAVE_WORD_SIZE is not 4, this code will have to change */ + if (num_powers > 2) { + MP_CHECKOK( mp_init_size(&accum[0], 3 * nLen + 2) ); + MP_CHECKOK( mp_init_size(&accum[1], 3 * nLen + 2) ); + MP_CHECKOK( mp_init_size(&accum[2], 3 * nLen + 2) ); + MP_CHECKOK( mp_init_size(&accum[3], 3 * nLen + 2) ); + mp_set(&accum[0], 1); + MP_CHECKOK( s_mp_to_mont(&accum[0], mmm, &accum[0]) ); + MP_CHECKOK( mp_copy(montBase, &accum[1]) ); + SQR(montBase, &accum[2]); + MUL_NOWEAVE(montBase, &accum[2], &accum[3]); + MP_CHECKOK( mpi_to_weave(accum, powers, nLen, num_powers) ); + if (first_window < 4) { + MP_CHECKOK( mp_copy(&accum[first_window], &accum1) ); + first_window = num_powers; + } + } else { + if (first_window == 0) { + mp_set(&accum1, 1); + MP_CHECKOK( s_mp_to_mont(&accum1, mmm, &accum1) ); + } else { + /* assert first_window == 1? */ + MP_CHECKOK( mp_copy(montBase, &accum1) ); + } + } + + /* + * calculate all the powers in the powers array. + * this adds 2**(k-1)-2 square operations over just calculating the + * odd powers where k is the window size in the two other mp_modexpt + * implementations in this file. We will get some of that + * back by not needing the first 'k' squares and one multiply for the + * first window */ + for (i = WEAVE_WORD_SIZE; i < num_powers; i++) { + int acc_index = i & (WEAVE_WORD_SIZE-1); /* i % WEAVE_WORD_SIZE */ + if ( i & 1 ) { + MUL_NOWEAVE(montBase, &accum[acc_index-1] , &accum[acc_index]); + /* we've filled the array do our 'per array' processing */ + if (acc_index == (WEAVE_WORD_SIZE-1)) { + MP_CHECKOK( mpi_to_weave(accum, powers + i - (WEAVE_WORD_SIZE-1), + nLen, num_powers) ); + + if (first_window <= i) { + MP_CHECKOK( mp_copy(&accum[first_window & (WEAVE_WORD_SIZE-1)], + &accum1) ); + first_window = num_powers; + } + } + } else { + /* up to 8 we can find 2^i-1 in the accum array, but at 8 we our source + * and target are the same so we need to copy.. After that, the + * value is overwritten, so we need to fetch it from the stored + * weave array */ + if (i > 2* WEAVE_WORD_SIZE) { + MP_CHECKOK(weave_to_mpi(&accum2, powers+i/2, nLen, num_powers)); + SQR(&accum2, &accum[acc_index]); + } else { + int half_power_index = (i/2) & (WEAVE_WORD_SIZE-1); + if (half_power_index == acc_index) { + /* copy is cheaper than weave_to_mpi */ + MP_CHECKOK(mp_copy(&accum[half_power_index], &accum2)); + SQR(&accum2,&accum[acc_index]); + } else { + SQR(&accum[half_power_index],&accum[acc_index]); + } + } + } + } + /* if the accum1 isn't set, Then there is something wrong with our logic + * above and is an internal programming error. + */ +#if MP_ARGCHK == 2 + assert(MP_USED(&accum1) != 0); +#endif + + /* set accumulator to montgomery residue of 1 */ + pa1 = &accum1; + pa2 = &accum2; + + for (expOff = bits_in_exponent - window_bits*2; expOff >= 0; expOff -= window_bits) { + mp_size smallExp; + MP_CHECKOK( mpl_get_bits(exponent, expOff, window_bits) ); + smallExp = (mp_size)res; + + /* handle unroll the loops */ + switch (window_bits) { + case 1: + if (!smallExp) { + SQR(pa1,pa2); SWAPPA; + } else if (smallExp & 1) { + SQR(pa1,pa2); MUL_NOWEAVE(montBase,pa2,pa1); + } else { + ABORT; + } + break; + case 6: + SQR(pa1,pa2); SQR(pa2,pa1); + /* fall through */ + case 4: + SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); + MUL(smallExp, pa1,pa2); SWAPPA; + break; + case 5: + SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); + SQR(pa1,pa2); MUL(smallExp,pa2,pa1); + break; + default: + ABORT; /* could do a loop? */ + } + } + + res = s_mp_redc(pa1, mmm); + mp_exch(pa1, result); + +CLEANUP: + mp_clear(&accum1); + mp_clear(&accum2); + mp_clear(&accum[0]); + mp_clear(&accum[1]); + mp_clear(&accum[2]); + mp_clear(&accum[3]); + /* PORT_Memset(powers,0,num_powers*nLen*sizeof(mp_digit)); */ + free(powersArray); + return res; +} +#undef SQR +#undef MUL +#endif mp_err mp_exptmod(const mp_int *inBase, const mp_int *exponent, const mp_int *modulus, mp_int *result) @@ -514,6 +1087,9 @@ mp_err mp_exptmod(const mp_int *inBase, const mp_int *exponent, int nLen; mp_int montBase, goodBase; mp_mont_modulus mmm; +#ifdef MP_USING_CACHE_SAFE_MOD_EXP + static unsigned int max_window_bits; +#endif /* function for computing n0prime only works if n0 is odd */ if (!mp_isodd(modulus)) @@ -546,6 +1122,21 @@ mp_err mp_exptmod(const mp_int *inBase, const mp_int *exponent, MP_CHECKOK( s_mp_to_mont(base, &mmm, &montBase) ); bits_in_exponent = mpl_significant_bits(exponent); +#ifdef MP_USING_CACHE_SAFE_MOD_EXP + if (mp_using_cache_safe_exp) { + if (bits_in_exponent > 780) + window_bits = 6; + else if (bits_in_exponent > 256) + window_bits = 5; + else if (bits_in_exponent > 20) + window_bits = 4; + /* RSA public key exponents are typically under 20 bits (common values + * are: 3, 17, 65537) and a 4-bit window is inefficient + */ + else + window_bits = 1; + } else +#endif if (bits_in_exponent > 480) window_bits = 6; else if (bits_in_exponent > 160) @@ -557,6 +1148,35 @@ mp_err mp_exptmod(const mp_int *inBase, const mp_int *exponent, */ else window_bits = 1; + +#ifdef MP_USING_CACHE_SAFE_MOD_EXP + /* + * clamp the window size based on + * the cache line size. + */ + if (!max_window_bits) { + unsigned long cache_size = s_mpi_getProcessorLineSize(); + /* processor has no cache, use 'fast' code always */ + if (cache_size == 0) { + mp_using_cache_safe_exp = 0; + } + if ((cache_size == 0) || (cache_size >= 64)) { + max_window_bits = 6; + } else if (cache_size >= 32) { + max_window_bits = 5; + } else if (cache_size >= 16) { + max_window_bits = 4; + } else max_window_bits = 1; /* should this be an assert? */ + } + + /* clamp the window size down before we caclulate bits_in_exponent */ + if (mp_using_cache_safe_exp) { + if (window_bits > max_window_bits) { + window_bits = max_window_bits; + } + } +#endif + odd_ints = 1 << (window_bits - 1); i = bits_in_exponent % window_bits; if (i != 0) { @@ -570,6 +1190,12 @@ mp_err mp_exptmod(const mp_int *inBase, const mp_int *exponent, bits_in_exponent, window_bits, odd_ints); } else #endif +#ifdef MP_USING_CACHE_SAFE_MOD_EXP + if (mp_using_cache_safe_exp) { + res = mp_exptmod_safe_i(&montBase, exponent, modulus, result, &mmm, nLen, + bits_in_exponent, window_bits, 1 << window_bits); + } else +#endif res = mp_exptmod_i(&montBase, exponent, modulus, result, &mmm, nLen, bits_in_exponent, window_bits, odd_ints); diff --git a/security/nss/lib/freebl/mpi/mpv_sparcv8.s b/security/nss/lib/freebl/mpi/mpv_sparcv8.s index 81fdd1b93..8cfa4d0c4 100644 --- a/security/nss/lib/freebl/mpi/mpv_sparcv8.s +++ b/security/nss/lib/freebl/mpi/mpv_sparcv8.s @@ -1,36 +1,39 @@ -!/* -! * The contents of this file are subject to the Mozilla Public -! * License Version 1.1 (the "License"); you may not use this file -! * except in compliance with the License. You may obtain a copy of -! * the License at http://www.mozilla.org/MPL/ -! * -! * Software distributed under the License is distributed on an "AS -! * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -! * implied. See the License for the specific language governing -! * rights and limitations under the License. -! * -! * The Original Code is a SPARC/VIS optimized multiply and add function -! * -! * The Initial Developer of the Original Code is Sun Microsystems Inc. -! * Portions created by Sun Microsystems Inc. are -! * Copyright (C) 1999-2000 Sun Microsystems Inc. All Rights Reserved. -! * -! * Contributor(s): -! * -! * Alternatively, the contents of this file may be used under the -! * terms of the GNU General Public License Version 2 or later (the -! * "GPL"), in which case the provisions of the GPL are applicable -! * instead of those above. If you wish to allow use of your -! * version of this file only under the terms of the GPL and not to -! * allow others to use your version of this file under the MPL, -! * indicate your decision by deleting the provisions above and -! * replace them with the notice and other provisions required by -! * the GPL. If you do not delete the provisions above, a recipient -! * may use your version of this file under either the MPL or the -! * GPL. -! * $Id$ -! */ - +! Inner multiply loop functions for hybrid 32/64-bit Sparc v8plus CPUs. +! ***** BEGIN LICENSE BLOCK ***** +! Version: MPL 1.1/GPL 2.0/LGPL 2.1 +! +! The contents of this file are subject to the Mozilla Public License Version +! 1.1 (the "License"); you may not use this file except in compliance with +! the License. You may obtain a copy of the License at +! http://www.mozilla.org/MPL/ +! +! Software distributed under the License is distributed on an "AS IS" basis, +! WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +! for the specific language governing rights and limitations under the +! License. +! +! The Original Code is a SPARC v8plus+VIS optimized multiply and add function +! +! The Initial Developer of the Original Code is Sun Microsystems Inc. +! Portions created by Sun Microsystems Inc. are +! Copyright (C) 2000-2005 Sun Microsystems Inc. All Rights Reserved. +! +! Contributor(s): +! +! Alternatively, the contents of this file may be used under the terms of +! either the GNU General Public License Version 2 or later (the "GPL"), or +! the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +! in which case the provisions of the GPL or the LGPL are applicable instead +! of those above. If you wish to allow use of your version of this file only +! under the terms of either the GPL or the LGPL, and not to allow others to +! use your version of this file under the terms of the MPL, indicate your +! decision by deleting the provisions above and replace them with the notice +! and other provisions required by the GPL or the LGPL. If you do not delete +! the provisions above, a recipient may use your version of this file under +! the terms of any one of the MPL, the GPL or the LGPL. +! +! ***** END LICENSE BLOCK ***** +! $Id$ .section ".text",#alloc,#execinstr /* 000000 3 ( 0 0) */ .file "mpv_sparc.c" @@ -40,7 +43,7 @@ ! ! OFFSET SOURCE LINE LABEL INSTRUCTION (ISSUE TIME) (COMPLETION TIME) - .L_const_seg_900000106: /* frequency 1.0 confidence 0.0 */ + .L_const_seg_900000106: /* frequency 1.0 confidence 0.0 */ /* 000000 19 ( 0 0) */ .word 1127219200,0 /* 0x0008 20 ( 0 0) */ .word 1105199103,-4194304 /* 0x0010 21 ( 0 0) */ .align 16 @@ -50,8 +53,8 @@ ! ENTRY mul_add ! - .global mul_add - mul_add: /* frequency 1.0 confidence 0.0 */ + .global mul_add + mul_add: /* frequency 1.0 confidence 0.0 */ /* 0x0010 29 ( 0 1) */ sethi %hi(0x1800),%g1 /* 0x0014 30 ( 0 1) */ sethi %hi(mask_cnst),%g2 /* 0x0018 31 ( 1 2) */ xor %g1,-984,%g1 @@ -62,7 +65,7 @@ ! ENTRY .L900000154 ! - .L900000154: /* frequency 1.0 confidence 0.0 */ + .L900000154: /* frequency 1.0 confidence 0.0 */ /* 0x0024 35 ( 0 2) */ call (.+0x8) ! params = ! Result = /* 0x0028 ( 1 2) */ sethi %hi((_GLOBAL_OFFSET_TABLE_-(.L900000154-.))),%g5 /* 0x002c 177 ( 2 3) */ sethi %hi(.L_const_seg_900000106),%g3 @@ -190,7 +193,7 @@ ! ENTRY .L77000037 ! - .L77000037: /* frequency 1.0 confidence 0.0 */ + .L77000037: /* frequency 1.0 confidence 0.0 */ /* 0x020c 307 ( 0 1) */ subcc %o2,16,%g0 /* 0x0210 308 ( 0 1) */ bne,pn %icc,.L77000076 ! tprob=0.50 /* 0x0214 ( 1 5) */ ldd [%o0],%f8 @@ -411,7 +414,7 @@ ! ENTRY .L77000076 ! - .L77000076: /* frequency 1.0 confidence 0.0 */ + .L77000076: /* frequency 1.0 confidence 0.0 */ /* 0x0568 540 ( 0 4) */ ldd [%o0],%f6 /* 0x056c 546 ( 0 1) */ add %o2,1,%g2 /* 0x0570 547 ( 0 3) */ fmovd %f0,%f14 @@ -454,7 +457,7 @@ ! ENTRY .L900000149 ! - .L900000149: /* frequency 1.0 confidence 0.0 */ + .L900000149: /* frequency 1.0 confidence 0.0 */ /* 0x05fc 586 ( 0 4) */ fxnor %f14,%f12,%f22 /* 0x0600 587 ( 0 5) */ fmuld %f4,%f16,%f4 /* 0x0604 588 ( 0 1) */ add %g2,2,%g2 @@ -491,7 +494,7 @@ ! ENTRY .L900000152 ! - .L900000152: /* frequency 1.0 confidence 0.0 */ + .L900000152: /* frequency 1.0 confidence 0.0 */ /* 0x0678 618 ( 0 4) */ fxnor %f14,%f12,%f12 /* 0x067c 619 ( 0 5) */ fmuld %f0,%f16,%f22 /* 0x0680 620 ( 0 1) */ add %o5,80,%o5 @@ -548,14 +551,14 @@ ! ENTRY .L77000077 ! - .L77000077: /* frequency 1.0 confidence 0.0 */ + .L77000077: /* frequency 1.0 confidence 0.0 */ /* 0x0744 670 ( 0 4) */ ldd [%g5],%f0 ! ! ENTRY .L900000160 ! - .L900000160: /* frequency 1.0 confidence 0.0 */ + .L900000160: /* frequency 1.0 confidence 0.0 */ /* 0x0748 672 ( 0 4) */ fxnor %f14,%f0,%f0 /* 0x074c 673 ( 0 1) */ add %g2,1,%g2 /* 0x0750 674 ( 0 1) */ add %g5,8,%g5 @@ -579,14 +582,14 @@ ! ENTRY .L77000043 ! - .L77000043: /* frequency 1.0 confidence 0.0 */ + .L77000043: /* frequency 1.0 confidence 0.0 */ /* 0x0790 696 ( 0 1) */ subcc %o3,0,%g0 ! ! ENTRY .L900000161 ! - .L900000161: /* frequency 1.0 confidence 0.0 */ + .L900000161: /* frequency 1.0 confidence 0.0 */ /* 0x0794 698 ( 0 1) */ ble,a,pt %icc,.L900000159 ! tprob=0.50 /* 0x0798 ( 0 1) */ or %g0,%o7,%i0 /* 0x079c 703 ( 0 2) */ ldx [%fp-2256],%o2 @@ -614,7 +617,7 @@ ! ENTRY .L900000145 ! - .L900000145: /* frequency 1.0 confidence 0.0 */ + .L900000145: /* frequency 1.0 confidence 0.0 */ /* 0x07ec 724 ( 0 2) */ ld [%g3],%o7 /* 0x07f0 725 ( 0 1) */ add %o2,%o3,%o2 /* 0x07f4 726 ( 0 1) */ sra %o0,0,%o3 @@ -647,7 +650,7 @@ ! ENTRY .L900000148 ! - .L900000148: /* frequency 1.0 confidence 0.0 */ + .L900000148: /* frequency 1.0 confidence 0.0 */ /* 0x0858 752 ( 0 1) */ add %o2,%o3,%o2 /* 0x085c 753 ( 0 1) */ sra %o0,0,%o3 /* 0x0860 754 ( 0 2) */ ld [%g3],%o0 @@ -667,14 +670,14 @@ ! ENTRY .L77000078 ! - .L77000078: /* frequency 1.0 confidence 0.0 */ + .L77000078: /* frequency 1.0 confidence 0.0 */ /* 0x0890 767 ( 0 2) */ ld [%g3],%o2 ! ! ENTRY .L900000158 ! - .L900000158: /* frequency 1.0 confidence 0.0 */ + .L900000158: /* frequency 1.0 confidence 0.0 */ /* 0x0894 769 ( 0 2) */ ldx [%g5],%o0 /* 0x0898 770 ( 0 1) */ sra %o7,0,%o1 /* 0x089c 771 ( 0 1) */ add %g4,1,%g4 @@ -693,7 +696,7 @@ ! ENTRY .L77000047 ! - .L77000047: /* frequency 1.0 confidence 0.0 */ + .L77000047: /* frequency 1.0 confidence 0.0 */ /* 0x08c8 783 ( 0 1) */ or %g0,%o7,%i0 /* 0x08cc ( 1 8) */ ret ! Result = %o1 %o0 %f0 %f1 /* 0x08d0 ( 3 5) */ restore %g0,%g0,%g0 @@ -702,7 +705,7 @@ ! ENTRY .L77000048 ! - .L77000048: /* frequency 1.0 confidence 0.0 */ + .L77000048: /* frequency 1.0 confidence 0.0 */ /* 0x08d4 794 ( 0 1) */ bne,pn %icc,.L77000050 ! tprob=0.50 /* 0x08d8 ( 0 1) */ sethi %hi(0xfff80000),%g2 /* 0x08dc 796 ( 0 4) */ ldd [%g5],%f4 @@ -872,7 +875,7 @@ ! ENTRY .L77000050 ! - .L77000050: /* frequency 1.0 confidence 0.0 */ + .L77000050: /* frequency 1.0 confidence 0.0 */ /* 0x0b64 978 ( 0 1) */ subcc %o2,16,%g0 /* 0x0b68 979 ( 0 1) */ bne,pn %icc,.L77000073 ! tprob=0.50 /* 0x0b6c ( 0 1) */ sethi %hi(0xfff80000),%g2 @@ -1180,14 +1183,14 @@ ! ENTRY .L77000061 ! - .L77000061: /* frequency 1.0 confidence 0.0 */ + .L77000061: /* frequency 1.0 confidence 0.0 */ /* 0x119c 1437 ( 0 1) */ or %g0,%o7,%i0 ! ! ENTRY .L900000159 ! - .L900000159: /* frequency 1.0 confidence 0.0 */ + .L900000159: /* frequency 1.0 confidence 0.0 */ /* 0x11a0 ( 0 7) */ ret ! Result = %o1 %o0 %f0 %f1 /* 0x11a4 ( 2 4) */ restore %g0,%g0,%g0 @@ -1195,9 +1198,7 @@ ! ENTRY .L77000073 ! - .L77000073: /* frequency 1.0 confidence 0.0 */ - - + .L77000073: /* frequency 1.0 confidence 0.0 */ or %g0, %i4, %o2 or %g0, %o0, %o1 or %g0, %i3, %o0 @@ -1206,7 +1207,7 @@ ! ENTRY .L77000052 ! - .L77000052: /* frequency 1.0 confidence 0.0 */ + .L77000052: /* frequency 1.0 confidence 0.0 */ /* 0x1028 1318 ( 0 1) */ andn %o2,%g2,%g2 /* 0x102c 1319 ( 0 1) */ st %g2,[%sp+96] /* 0x1030 1325 ( 0 1) */ add %o0,1,%g3 @@ -1269,7 +1270,7 @@ ! ENTRY .L990000154 ! - .L990000154: /* frequency 1.0 confidence 0.0 */ + .L990000154: /* frequency 1.0 confidence 0.0 */ /* 0x110c 1384 ( 0 3) */ ldd [%o1],%f24 /* 0x1110 1385 ( 0 1) */ add %g4,3,%g4 /* 0x1114 1386 ( 0 1) */ add %o4,96,%o4 @@ -1339,7 +1340,7 @@ ! ENTRY .L990000157 ! - .L990000157: /* frequency 1.0 confidence 0.0 */ + .L990000157: /* frequency 1.0 confidence 0.0 */ /* 0x120c 1449 ( 0 3) */ fitod %f12,%f28 /* 0x1210 1450 ( 0 3) */ fmuld %f6,%f18,%f24 /* 0x1214 1451 ( 0 1) */ add %g3,128,%g3 @@ -1409,14 +1410,14 @@ ! ENTRY .L77000054 ! - .L77000054: /* frequency 1.0 confidence 0.0 */ + .L77000054: /* frequency 1.0 confidence 0.0 */ /* 0x130c 1514 ( 0 3) */ ldd [%o1],%f0 ! ! ENTRY .L990000161 ! - .L990000161: /* frequency 1.0 confidence 0.0 */ + .L990000161: /* frequency 1.0 confidence 0.0 */ /* 0x1310 1516 ( 0 2) */ fxnor %f14,%f0,%f0 /* 0x1314 1517 ( 0 1) */ add %g4,1,%g4 /* 0x1318 1518 ( 0 1) */ add %o1,8,%o1 @@ -1448,14 +1449,14 @@ ! ENTRY .L77000056 ! - .L77000056: /* frequency 1.0 confidence 0.0 */ + .L77000056: /* frequency 1.0 confidence 0.0 */ /* 0x1378 1548 ( 0 1) */ subcc %o0,0,%g0 ! ! ENTRY .L990000162 ! - .L990000162: /* frequency 1.0 confidence 0.0 */ + .L990000162: /* frequency 1.0 confidence 0.0 */ /* 0x137c 1550 ( 0 1) */ bleu,pt %icc,.L77770061 ! tprob=0.50 /* 0x1380 ( 0 1) */ nop /* 0x1384 1555 ( 0 1) */ sethi %hi(0x1800),%g1 @@ -1500,7 +1501,7 @@ ! ENTRY .L990000142 ! - .L990000142: /* frequency 1.0 confidence 0.0 */ + .L990000142: /* frequency 1.0 confidence 0.0 */ /* 0x1418 1593 ( 0 1) */ add %o2,%o3,%o2 /* 0x141c 1594 ( 0 1) */ add %i2,4,%i2 /* 0x1420 1595 ( 0 2) */ ld [%g4],%o3 @@ -1550,7 +1551,7 @@ ! ENTRY .L990000145 ! - .L990000145: /* frequency 1.0 confidence 0.0 */ + .L990000145: /* frequency 1.0 confidence 0.0 */ /* 0x14c8 1638 ( 0 1) */ add %o2,%o3,%o3 /* 0x14cc 1639 ( 0 1) */ add %g3,4,%g3 /* 0x14d0 1640 ( 1 2) */ srl %o0,0,%o2 @@ -1565,14 +1566,14 @@ ! ENTRY .L77000058 ! - .L77000058: /* frequency 1.0 confidence 0.0 */ + .L77000058: /* frequency 1.0 confidence 0.0 */ /* 0x14ec 1648 ( 0 2) */ ldx [%g2],%o2 ! ! ENTRY .L990000160 ! - .L990000160: /* frequency 1.0 confidence 0.0 */ + .L990000160: /* frequency 1.0 confidence 0.0 */ /* 0x14f0 1650 ( 0 1) */ sllx %o2,19,%o3 /* 0x14f4 1651 ( 0 2) */ ldx [%g5],%o0 /* 0x14f8 1652 ( 0 1) */ add %i2,1,%i2 @@ -1595,13 +1596,10 @@ ! ENTRY .L77770061 ! - .L77770061: /* frequency 1.0 confidence 0.0 */ + .L77770061: /* frequency 1.0 confidence 0.0 */ /* 0x1534 ( 0 2) */ ret ! Result = %o1 %o0 %f0 %f1 /* 0x1538 ( 2 3) */ restore %g0,%o5,%o0 - - - /* 0x11a8 1441 ( 0 0) */ .type mul_add,2 /* 0x11a8 1442 ( 0 0) */ .size mul_add,(.-mul_add) /* 0x11a8 1445 ( 0 0) */ .align 16 @@ -1611,8 +1609,8 @@ ! ENTRY mul_add_inp ! - .global mul_add_inp - mul_add_inp: /* frequency 1.0 confidence 0.0 */ + .global mul_add_inp + mul_add_inp: /* frequency 1.0 confidence 0.0 */ /* 0x11b0 1453 ( 0 1) */ or %g0,%o2,%g1 /* 0x11b4 1454 ( 0 1) */ or %g0,%o3,%o4 /* 0x11b8 1455 ( 1 2) */ or %g0,%o0,%g3 @@ -1633,7 +1631,7 @@ ! ENTRY mask_cnst ! - mask_cnst: /* frequency 1.0 confidence 0.0 */ + mask_cnst: /* frequency 1.0 confidence 0.0 */ /* 0x11d8 8 ( 0 0) */ .word -2147483648 /* 0x11dc 9 ( 0 0) */ .word -2147483648 /* 0x11e0 10 ( 0 0) */ .type mask_cnst,#object diff --git a/security/nss/lib/freebl/mpi/mpv_sparcv8x.s b/security/nss/lib/freebl/mpi/mpv_sparcv8x.s new file mode 100644 index 000000000..154d69965 --- /dev/null +++ b/security/nss/lib/freebl/mpi/mpv_sparcv8x.s @@ -0,0 +1,175 @@ +! Inner multiply loop functions for pure 32-bit Sparc v8 CPUs. +! ***** BEGIN LICENSE BLOCK ***** +! Version: MPL 1.1/GPL 2.0/LGPL 2.1 +! +! The contents of this file are subject to the Mozilla Public License Version +! 1.1 (the "License"); you may not use this file except in compliance with +! the License. You may obtain a copy of the License at +! http://www.mozilla.org/MPL/ +! +! Software distributed under the License is distributed on an "AS IS" basis, +! WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +! for the specific language governing rights and limitations under the +! License. +! +! The Original Code is a SPARC v8 optimized multiply and add function +! +! The Initial Developer of the Original Code is Sun Microsystems Inc. +! Portions created by Sun Microsystems Inc. are +! Copyright (C) 2000-2005 Sun Microsystems Inc. All Rights Reserved. +! +! Contributor(s): +! +! Alternatively, the contents of this file may be used under the terms of +! either the GNU General Public License Version 2 or later (the "GPL"), or +! the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +! in which case the provisions of the GPL or the LGPL are applicable instead +! of those above. If you wish to allow use of your version of this file only +! under the terms of either the GPL or the LGPL, and not to allow others to +! use your version of this file under the terms of the MPL, indicate your +! decision by deleting the provisions above and replace them with the notice +! and other provisions required by the GPL or the LGPL. If you do not delete +! the provisions above, a recipient may use your version of this file under +! the terms of any one of the MPL, the GPL or the LGPL. +! +! ***** END LICENSE BLOCK ***** + +! $Id$ + + .file "mpv_sparcv8x.s" + .align 8 + + .section ".text",#alloc,#execinstr + .global s_mpv_mul_d + s_mpv_mul_d: + save %sp, -0x60, %sp + mov %i0, %o0 + clr %g4 + cmp %i1, 0x0 + be .L103 + sub %i1, 0x1, %o5 + ld [%o0], %g1 +.L101: + umul %g1, %i2, %g2 + rd %y, %g1 + add %g2, %g4, %g3 + mov %g1, %o4 + add %o0, 0x4, %o0 + cmp %g3, %g4 + blu,a .L102 + add %g1, 0x1, %o4 +.L102: + st %g3, [%i3] + mov %o5, %g1 + add %i3, 0x4, %i3 + cmp %g1, 0x0 + mov %o4, %g4 + sub %o5, 0x1, %o5 + bne,a .L101 + ld [%o0], %g1 +.L103: + st %g4, [%i3] + ret + restore + + .type s_mpv_mul_d,2 + .size s_mpv_mul_d,(.-s_mpv_mul_d) + + .align 16 + .global s_mpv_mul_d_add + s_mpv_mul_d_add: + + save %sp, -0x60, %sp + mov %i0, %o0 + clr %g4 + cmp %i1, 0x0 + be .L204 + sub %i1, 0x1, %o5 + ld [%o0], %g1 +.L201: + umul %g1, %i2, %g2 + rd %y, %g1 + add %g2, %g4, %g3 + mov %g1, %o4 + add %o0, 0x4, %o0 + cmp %g3, %g4 + blu,a .L202 + add %g1, 0x1, %o4 +.L202: + ld [%i3], %g2 + add %g3, %g2, %g1 + cmp %g1, %g2 + blu,a .L203 + add %o4, 0x1, %o4 +.L203: + st %g1, [%i3] + mov %o5, %g1 + add %i3, 0x4, %i3 + cmp %g1, 0x0 + mov %o4, %g4 + sub %o5, 0x1, %o5 + bne,a .L201 + ld [%o0], %g1 +.L204: + st %g4, [%i3] + ret + restore + + .type s_mpv_mul_d_add,2 + .size s_mpv_mul_d_add,(.-s_mpv_mul_d_add) + + .align 16 + .global s_mpv_mul_d_add_prop + s_mpv_mul_d_add_prop: + + save %sp, -0x60, %sp + mov %i0, %o0 + clr %o5 + cmp %i1, 0x0 + be .L30x70 + sub %i1, 0x1, %g4 + ld [%o0], %g1 +.L30x1c: + umul %g1, %i2, %g2 + rd %y, %g1 + add %g2, %o5, %g3 + mov %g1, %o4 + add %o0, 0x4, %o0 + cmp %g3, %o5 + blu,a .L30x3c + add %g1, 0x1, %o4 +.L30x3c: + ld [%i3], %g2 + add %g3, %g2, %g1 + cmp %g1, %g2 + blu,a .L30x50 + add %o4, 0x1, %o4 +.L30x50: + st %g1, [%i3] + mov %g4, %g1 + add %i3, 0x4, %i3 + cmp %g1, 0x0 + mov %o4, %o5 + sub %g4, 0x1, %g4 + bne,a .L30x1c + ld [%o0], %g1 +.L30x70: + cmp %o5, 0x0 + be .L30xa0 + nop + ld [%i3], %g1 +.L30x80: + add %o5, %g1, %g2 + st %g2, [%i3] + add %i3, 0x4, %i3 + cmp %g2, %g1 + addx %g0, 0x0, %o5 + cmp %o5, 0x0 + bne,a .L30x80 + ld [%i3], %g1 +.L30xa0: + ret + restore + + .type s_mpv_mul_d_add_prop,2 + .size s_mpv_mul_d_add_prop,(.-s_mpv_mul_d_add_prop) diff --git a/security/nss/lib/freebl/mpi/target.mk b/security/nss/lib/freebl/mpi/target.mk index 0edaf8813..c17854819 100644 --- a/security/nss/lib/freebl/mpi/target.mk +++ b/security/nss/lib/freebl/mpi/target.mk @@ -206,7 +206,7 @@ ifeq ($(TARGET),x86LINUX) #Linux AS_OBJS = mpi_x86.o MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D -MPICMN += -DMP_MONT_USE_MP_MUL +MPICMN += -DMP_MONT_USE_MP_MUL -DMP_CHAR_STORE_SLOW -DMP_IS_LITTLE_ENDIAN CFLAGS= -O2 -fPIC -DLINUX1_2 -Di386 -D_XOPEN_SOURCE -DLINUX2_1 -ansi -Wall \ -pipe -DLINUX -Dlinux -D_POSIX_SOURCE -D_BSD_SOURCE -DHAVE_STRERROR \ -DXP_UNIX -UDEBUG -DNDEBUG -D_REENTRANT $(MPICMN) @@ -222,6 +222,7 @@ ifeq ($(TARGET),AMD64SOLARIS) ASFLAGS += -xarch=generic64 AS_OBJS = mpi_amd64.o mpi_amd64_sun.o MP_CONFIG = -DMP_ASSEMBLY_MULTIPLY -DMPI_AMD64 +MP_CONFIG += -DMP_CHAR_STORE_SLOW -DMP_IS_LITTLE_ENDIAN CFLAGS = -xarch=generic64 -xO4 -I. -DMP_API_COMPATIBLE -DMP_IOFUNC $(MP_CONFIG) MPICMN += $(MP_CONFIG) diff --git a/security/nss/lib/freebl/pqg.c b/security/nss/lib/freebl/pqg.c index 4f9f15362..c3e92c62d 100644 --- a/security/nss/lib/freebl/pqg.c +++ b/security/nss/lib/freebl/pqg.c @@ -76,13 +76,11 @@ static const unsigned char fips_186_1_a5_pqseed[] = { ** global random number generator. */ static SECStatus -getPQseed(SECItem *seed) +getPQseed(SECItem *seed, PRArenaPool* arena) { - if (seed->data) { - PORT_Free(seed->data); - seed->data = NULL; + if (!seed->data) { + seed->data = (unsigned char*)PORT_ArenaZAlloc(arena, seed->len); } - seed->data = (unsigned char*)PORT_ZAlloc(seed->len); if (!seed->data) { PORT_SetError(SEC_ERROR_NO_MEMORY); return SECFailure; @@ -455,7 +453,7 @@ step_1: goto cleanup; } seed->len = seedBytes; - CHECK_SEC_OK( getPQseed(seed) ); + CHECK_SEC_OK( getPQseed(seed, verify->arena) ); /* ****************************************************************** ** Step 2. ** "Compute U = SHA[SEED] XOR SHA[(SEED+1) mod 2**g]." @@ -569,6 +567,9 @@ cleanup: PORT_FreeArena(params->arena, PR_TRUE); PORT_FreeArena(verify->arena, PR_TRUE); } + if (hit.data) { + SECITEM_FreeItem(&hit, PR_FALSE); + } return rv; } diff --git a/security/nss/lib/freebl/prng_fips1861.c b/security/nss/lib/freebl/prng_fips1861.c index bcc85a79d..900b98ab8 100644 --- a/security/nss/lib/freebl/prng_fips1861.c +++ b/security/nss/lib/freebl/prng_fips1861.c @@ -47,6 +47,7 @@ #include "secitem.h" #include "sha_fast.h" #include "secrng.h" /* for RNG_GetNoise() */ +#include "secmpi.h" /* * The minimum amount of seed data required before the generator will @@ -63,57 +64,93 @@ #define MIN_SEED_COUNT 1024 /* - * Steps taken from FIPS 186-1 Appendix 3.1 + * Steps taken from Algorithm 1 of FIPS 186-2 Change Notice 1 */ /* - * According to FIPS 186-1, 160 <= b <= 512 - * For our purposes, we will assume b == 160 + * According to FIPS 186-2, 160 <= b <= 512. + * For our purposes, we will assume b == 160, + * 256, or 512 (the output size of SHA-1, + * SHA-256, or SHA-512). */ -#define FIPS_B 160 -#define BSIZE FIPS_B / BITS_PER_BYTE +#define FIPS_B 256 +#define B_HASH_BUF SHA256_HashBuf +#define BSIZE (FIPS_B / PR_BITS_PER_BYTE) + +/* Output size of the G function */ +#define FIPS_G 160 +#define GSIZE (FIPS_G / PR_BITS_PER_BYTE) /* - * Add two 160-bit numbers represented as arrays of 20 bytes. + * Add two b-bit numbers represented as arrays of BSIZE bytes. * The numbers are big-endian, MSB first, so addition is done * from the end of the buffer to the beginning. */ -#define ADD_160BIT_PLUS_CARRY(dest, add1, add2, cy) \ +#define ADD_B_BIT_PLUS_CARRY(dest, add1, add2, cy) \ carry = cy; \ - for (i=BSIZE-1; i>=0; --i) { \ - carry += add1[i] + add2[i]; \ - dest[i] = (PRUint8)carry; \ + for (k=BSIZE-1; k>=0; --k) { \ + carry += add1[k] + add2[k]; \ + dest[k] = (PRUint8)carry; \ carry >>= 8; \ } -#define ADD_160BIT_2(dest, add1, add2) \ - ADD_160BIT_PLUS_CARRY(dest, add1, add2, 0) +#define ADD_B_BIT_2(dest, add1, add2) \ + ADD_B_BIT_PLUS_CARRY(dest, add1, add2, 0) /* - * FIPS requires result from Step 3c to be reduced mod q when generating + * FIPS requires result from Step 3.3 to be reduced mod q when generating * random numbers for DSA. - * by definition q >= 2^159 + 1, thus xj < 2q - * thus reducing mod q is simple subtraction when xj > q + * + * Input: w, 2*GSIZE bytes + * q, DSA_SUBPRIME_LEN bytes + * Output: xj, DSA_SUBPRIME_LEN bytes */ -#define dsa_reduce_mod_q(xj, q) \ - PORT_Assert(q[0] >= 0x80); \ - if (memcmp(xj,q,BSIZE) > 0) { \ - carry = 0; \ - for (i=BSIZE-1; i>=0; --i) { \ - carry += (signed int)xj[i] - (signed int)q[i]; \ - xj[i] = (PRUint8)carry; \ - carry >>= 8; \ - } \ +static SECStatus +dsa_reduce_mod_q(const unsigned char *w, const unsigned char *q, + unsigned char *xj) +{ + mp_int W, Q, Xj; + mp_err err; + SECStatus rv = SECSuccess; + + /* Initialize MPI integers. */ + MP_DIGITS(&W) = 0; + MP_DIGITS(&Q) = 0; + MP_DIGITS(&Xj) = 0; + CHECK_MPI_OK( mp_init(&W) ); + CHECK_MPI_OK( mp_init(&Q) ); + CHECK_MPI_OK( mp_init(&Xj) ); + /* + * Convert input arguments into MPI integers. + */ + CHECK_MPI_OK( mp_read_unsigned_octets(&W, w, 2*GSIZE) ); + CHECK_MPI_OK( mp_read_unsigned_octets(&Q, q, DSA_SUBPRIME_LEN) ); + /* + * Algorithm 1 of FIPS 186-2 Change Notice 1, Step 3.3 + * + * xj = (w0 || w1) mod q + */ + CHECK_MPI_OK( mp_mod(&W, &Q, &Xj) ); + CHECK_MPI_OK( mp_to_fixlen_octets(&Xj, xj, DSA_SUBPRIME_LEN) ); +cleanup: + mp_clear(&W); + mp_clear(&Q); + mp_clear(&Xj); + if (err) { + MP_TO_SEC_ERROR(err); + rv = SECFailure; } + return rv; +} /* * Specialized SHA1-like function. This function appends zeroes to a * single input block and runs a single instance of the compression function, - * as specified in FIPS 186-1 appendix 3.3. + * as specified in FIPS 186-2 appendix 3.3. */ -void -RNG_UpdateAndEnd_FIPS186_1(SHA1Context *ctx, +static void +RNG_UpdateAndEnd_FIPS186_2(SHA1Context *ctx, unsigned char *input, unsigned int inputLen, unsigned char *hashout, unsigned int *pDigestLen, unsigned int maxDigestLen); @@ -123,9 +160,9 @@ RNG_UpdateAndEnd_FIPS186_1(SHA1Context *ctx, */ struct RNGContextStr { PRUint8 XKEY[BSIZE]; /* Seed for next SHA iteration */ - PRUint8 Xj[BSIZE]; /* Output from previous operation */ + PRUint8 Xj[2*GSIZE]; /* Output from previous operation. */ PZLock *lock; /* Lock to serialize access to global rng */ - PRUint8 avail; /* # bytes of output available, [0...20] */ + PRUint8 avail; /* # bytes of output available, [0...2*GSIZE] */ PRUint32 seedCount; /* number of seed bytes given to generator */ PRBool isValid; /* false if RNG reaches an invalid state */ }; @@ -144,79 +181,115 @@ freeRNGContext() } /* - * Implementation of the algorithm in FIPS 186-1 appendix 3.1, heretofore - * called alg3_1(). It is assumed a lock for the global rng context has - * already been acquired. + * Implementation of Algorithm 1 of FIPS 186-2 Change Notice 1, + * hereinafter called alg_cn_1(). It is assumed a lock for the global + * rng context has already been acquired. * Calling this function with XSEEDj == NULL is equivalent to saying there * is no optional user input, which is further equivalent to saying that * the optional user input is 0. */ static SECStatus -alg_fips186_1_x3_1(RNGContext *rng, - const unsigned char *XSEEDj, unsigned char *q) +alg_fips186_2_cn_1(RNGContext *rng, const unsigned char *XSEEDj) { /* SHA1 context for G(t, XVAL) function */ SHA1Context sha1cx; + /* XKEY for iteration 1 */ + PRUint8 XKEY_1[BSIZE]; + const PRUint8 *XKEY_old; + PRUint8 *XKEY_new; /* input to hash function */ PRUint8 XVAL[BSIZE]; /* store a copy of the output to compare with the previous output */ - PRUint8 x_j[BSIZE]; - /* used by ADD_160BIT macros */ - int i, carry; + PRUint8 x_j[2*GSIZE]; + /* used by ADD_B_BIT macros */ + int k, carry; + /* store the output of G(t, XVAL) in the rightmost GSIZE bytes */ + PRUint8 w_i[BSIZE]; + int i; unsigned int len; + SECStatus rv = SECSuccess; + if (!rng->isValid) { /* RNG has alread entered an invalid state. */ - PORT_SetError(SEC_ERROR_INVALID_ARGS); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } +#if GSIZE < BSIZE + /* zero the leftmost bytes so we can pass it to ADD_B_BIT_PLUS_CARRY */ + memset(w_i, 0, BSIZE - GSIZE); +#endif /* - * <Step 2> Initialize t, taken care of in SHA-1 (same initial values) - */ - SHA1_Begin(&sha1cx); - /* - * <Step 3a> XSEEDj is optional user input - * - * <Step 3b> XVAL = (XKEY + XSEEDj) mod 2^b - * :always reduced mod 2^b, since storing as 160-bit value - */ - if (XSEEDj) { - /* XSEEDj > 0 */ - ADD_160BIT_2(XVAL, rng->XKEY, XSEEDj); - } else { - /* XSEEDj == 0 */ - memcpy(XVAL, rng->XKEY, BSIZE); - } - /* - * <Step 3c> Xj = G(t, XVAL) mod q - * :In this code, (mod q) is only understood for DSA ops, - * :not general RNG (what would q be in non-DSA uses?). - * :If a q is specified, use it. - * :FIPS 186-1 specifies a different padding than the SHA1 180-1 - * :specification, this function is implemented below. + * <Step 2> Initialize t, taken care of in SHA-1 (same initial values) + * + * <Step 3.1> XSEEDj is optional user input */ - RNG_UpdateAndEnd_FIPS186_1(&sha1cx, XVAL, BSIZE, x_j, &len, BSIZE); - if (q != NULL) { - dsa_reduce_mod_q(x_j, q); + for (i = 0; i < 2; i++) { + /* only update rng->XKEY when both iterations have been completed */ + if (i == 0) { + /* for iteration 0 */ + XKEY_old = rng->XKEY; + XKEY_new = XKEY_1; + } else { + /* for iteration 1 */ + XKEY_old = XKEY_1; + XKEY_new = rng->XKEY; + } + /* + * <Step 3.2a> XVAL = (XKEY + XSEEDj) mod 2^b + * :always reduced mod 2^b, since storing as b-bit value + */ + if (XSEEDj) { + /* XSEEDj > 0 */ + if (memcmp(XKEY_old, XSEEDj, BSIZE) == 0) { + /* Should we add the error code SEC_ERROR_BAD_RNG_SEED? */ + PORT_SetError(SEC_ERROR_INVALID_ARGS); + rv = SECFailure; + goto done; + } + ADD_B_BIT_2(XVAL, XKEY_old, XSEEDj); + } else { + /* XSEEDj == 0 */ + memcpy(XVAL, XKEY_old, BSIZE); + } + /* + * <Step 3.2b> Wi = G(t, XVAL) + * :FIPS 186-2 specifies a different padding than the SHA1 180-1 + * :specification, this function is implemented in + * :RNG_UpdateAndEnd_FIPS186_2 below. + */ + SHA1_Begin(&sha1cx); + RNG_UpdateAndEnd_FIPS186_2(&sha1cx, XVAL, BSIZE, + &w_i[BSIZE - GSIZE], &len, GSIZE); + /* + * <Step 3.2c> XKEY = (1 + XKEY + Wi) mod 2^b + * :always reduced mod 2^b, since storing as 160-bit value + */ + ADD_B_BIT_PLUS_CARRY(XKEY_new, XKEY_old, w_i, 1); + /* + * <Step 3.3> Xj = (W0 || W1) + */ + memcpy(&x_j[i*GSIZE], &w_i[BSIZE - GSIZE], GSIZE); } - /* [FIPS 140-1] verify output does not match previous output */ - if (memcmp(x_j, rng->Xj, BSIZE) == 0) { - /* failed FIPS 140-1 continuous RNG condition. RNG now invalid. */ + /* [FIPS 140-2] verify output does not match previous output */ + if (memcmp(x_j, rng->Xj, 2*GSIZE) == 0) { + /* failed FIPS 140-2 continuous RNG test. RNG now invalid. */ rng->isValid = PR_FALSE; - return SECFailure; + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + rv = SECFailure; + goto done; } /* Xj is the output */ - memcpy(rng->Xj, x_j, BSIZE); - /* - * <Step 3d> XKEY = (1 + XKEY + Xj) mod 2^b - * :always reduced mod 2^b, since storing as 160-bit value - */ - ADD_160BIT_PLUS_CARRY(rng->XKEY, rng->XKEY, x_j, 1); - /* Always have a full buffer after executing alg3_1() */ - rng->avail = BSIZE; + memcpy(rng->Xj, x_j, 2*GSIZE); + /* Always have a full buffer after executing alg_cn_1() */ + rng->avail = 2*GSIZE; + +done: /* housekeeping */ - memset(x_j, 0, BSIZE); + memset(&w_i[BSIZE - GSIZE], 0, GSIZE); + memset(x_j, 0, 2*GSIZE); memset(XVAL, 0, BSIZE); - return SECSuccess; + memset(XKEY_1, 0, BSIZE); + return rv; } /* Use NSPR to prevent RNG_RNGInit from being called from separate @@ -237,6 +310,8 @@ static PRStatus rng_init(void) /* create a lock for it */ globalrng->lock = PZ_NewLock(nssILockOther); if (globalrng->lock == NULL) { + PORT_Free(globalrng); + globalrng = NULL; PORT_SetError(PR_OUT_OF_MEMORY_ERROR); return PR_FAILURE; } @@ -246,7 +321,7 @@ static PRStatus rng_init(void) numBytes = RNG_GetNoise(bytes, sizeof bytes); RNG_RandomUpdate(bytes, numBytes); } - return (globalrng != NULL) ? PR_SUCCESS : PR_FAILURE; + return PR_SUCCESS; } /* @@ -271,9 +346,8 @@ RNG_RNGInit(void) ** Update the global random number generator with more seeding ** material */ -SECStatus -prng_RandomUpdate(RNGContext *rng, const void *data, size_t bytes, - unsigned char *q) +static SECStatus +prng_RandomUpdate(RNGContext *rng, const void *data, size_t bytes) { SECStatus rv = SECSuccess; unsigned char inputhash[BSIZE]; @@ -292,9 +366,9 @@ prng_RandomUpdate(RNGContext *rng, const void *data, size_t bytes, if (bytes == BSIZE) memcpy(inputhash, data, BSIZE); else - rv = SHA1_HashBuf(inputhash, data, bytes); + rv = B_HASH_BUF(inputhash, data, bytes); if (rv != SECSuccess) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); + /* B_HASH_BUF set error */ return SECFailure; } /* --- LOCKED --- */ @@ -303,13 +377,13 @@ prng_RandomUpdate(RNGContext *rng, const void *data, size_t bytes, * Random information is initially supplied by a call to * RNG_SystemInfoForRNG(). That function collects entropy from * the system and calls RNG_RandomUpdate() to seed the generator. - * FIPS 186-1 3.1 step 1 specifies that a secret value for the - * seed-key must be chosen before the generator can begin. The - * size of XKEY is b-bytes, so fill it with the first b-bytes - * sent to RNG_RandomUpdate(). + * Algorithm 1 of FIPS 186-2 Change Notice 1, step 1 specifies that + * a secret value for the seed-key must be chosen before the + * generator can begin. The size of XKEY is b bits, so fill it + * with the first b bits sent to RNG_RandomUpdate(). */ if (rng->seedCount == 0) { - /* This is the first call to RandomUpdate(). Use a SHA1 hash + /* This is the first call to RandomUpdate(). Use a hash * of the input to set the seed, XKEY. * * <Step 1> copy seed bytes into context's XKEY @@ -320,19 +394,20 @@ prng_RandomUpdate(RNGContext *rng, const void *data, size_t bytes, * initialize XKEY, the "optional user input" at this stage * will be a pad of zeros, XSEEDj = 0. */ - rv = alg_fips186_1_x3_1(rng, NULL, q); - /* As per FIPS 140-1 continuous RNG requirement, the first + rv = alg_fips186_2_cn_1(rng, NULL); + /* As per FIPS 140-2 continuous RNG test requirement, the first * iteration of output is discarded. So here there is really - * no output available. This forces another execution of alg3_1() + * no output available. This forces another execution of alg_cn_1() * before any bytes can be extracted from the generator. */ rng->avail = 0; } else { - /* Execute the algorithm from FIPS 186-1 appendix 3.1 */ - rv = alg_fips186_1_x3_1(rng, inputhash, q); + /* Execute the algorithm from FIPS 186-2 Change Notice 1 */ + rv = alg_fips186_2_cn_1(rng, inputhash); } /* If got this far, have added bytes of seed data. */ - rng->seedCount += bytes; + if (rv == SECSuccess) + rng->seedCount += bytes; PZ_Unlock(rng->lock); /* --- UNLOCKED --- */ /* housekeeping */ @@ -342,12 +417,12 @@ prng_RandomUpdate(RNGContext *rng, const void *data, size_t bytes, /* ** Update the global random number generator with more seeding -** material. Not DSA, so no q. +** material. */ SECStatus RNG_RandomUpdate(const void *data, size_t bytes) { - return prng_RandomUpdate(globalrng, data, bytes, NULL); + return prng_RandomUpdate(globalrng, data, bytes); } /* @@ -356,7 +431,7 @@ RNG_RandomUpdate(const void *data, size_t bytes) */ SECStatus prng_GenerateGlobalRandomBytes(RNGContext *rng, - void *dest, size_t len, unsigned char *q) + void *dest, size_t len) { PRUint8 num; SECStatus rv = SECSuccess; @@ -379,18 +454,21 @@ prng_GenerateGlobalRandomBytes(RNGContext *rng, } /* * If there are enough bytes of random data, send back Xj, - * else call alg3_1() with 0's to generate more random data. + * else call alg_cn_1() with 0's to generate more random data. */ while (len > 0 && rv == SECSuccess) { if (rng->avail == 0) { /* All available bytes are used, so generate more. */ - rv = alg_fips186_1_x3_1(rng, NULL, q); + rv = alg_fips186_2_cn_1(rng, NULL); } - /* number of bytes to obtain on this iteration (max of 20) */ + /* number of bytes to obtain on this iteration (max of 40) */ num = PR_MIN(rng->avail, len); - /* if avail < BSIZE, the first avail bytes have already been used. */ + /* + * if avail < 2*GSIZE, the first 2*GSIZE - avail bytes have + * already been used. + */ if (num) { - memcpy(output, rng->Xj + (BSIZE - rng->avail), num); + memcpy(output, rng->Xj + (2*GSIZE - rng->avail), num); rng->avail -= num; len -= num; output += num; @@ -403,12 +481,12 @@ prng_GenerateGlobalRandomBytes(RNGContext *rng, /* ** Generate some random bytes, using the global random number generator -** object. Not DSA, so no q. +** object. */ SECStatus RNG_GenerateGlobalRandomBytes(void *dest, size_t len) { - return prng_GenerateGlobalRandomBytes(globalrng, dest, len, NULL); + return prng_GenerateGlobalRandomBytes(globalrng, dest, len); } void @@ -417,7 +495,8 @@ RNG_RNGShutdown(void) /* check for a valid global RNG context */ PORT_Assert(globalrng != NULL); if (globalrng == NULL) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); + /* Should set a "not initialized" error code. */ + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return; } /* clear */ @@ -429,20 +508,20 @@ RNG_RNGShutdown(void) /* * SHA: Generate hash value from context * Specialized function for PRNG - * The PRNG specified in FIPS 186-1 3.3 uses a function, G, + * The PRNG specified in FIPS 186-2 3.3 uses a function, G, * which has the same initialization and compression functions - * as SHA1 180-1, but uses different padding. FIPS 186-1 3.3 + * as SHA1 180-1, but uses different padding. FIPS 186-2 3.3 * specifies that the message be padded with 0's until the size * reaches 512 bits. */ -void -RNG_UpdateAndEnd_FIPS186_1(SHA1Context *ctx, +static void +RNG_UpdateAndEnd_FIPS186_2(SHA1Context *ctx, unsigned char *input, unsigned int inputLen, unsigned char *hashout, unsigned int *pDigestLen, unsigned int maxDigestLen) { -#if defined(IS_LITTLE_ENDIAN) - register PRUint32 A; +#if defined(SHA_NEED_TMP_VARIABLE) + register PRUint32 tmp; #endif static const unsigned char bulk_pad0[64] = { 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -465,55 +544,43 @@ RNG_UpdateAndEnd_FIPS186_1(SHA1Context *ctx, /* * Output hash */ -#if defined(IS_LITTLE_ENDIAN) - SHA_BYTESWAP(ctx->H[0]); - SHA_BYTESWAP(ctx->H[1]); - SHA_BYTESWAP(ctx->H[2]); - SHA_BYTESWAP(ctx->H[3]); - SHA_BYTESWAP(ctx->H[4]); -#endif - memcpy(hashout, ctx->H, SHA1_LENGTH); + SHA_STORE_RESULT; *pDigestLen = SHA1_LENGTH; - - /* - * Re-initialize the context (also zeroizes contents) - */ - SHA1_Begin(ctx); } /* * Specialized RNG for DSA * - * As per FIPS 186-1 appendix 3.1, in step 5 the value Xj should - * be reduced mod q, a 160-bit prime number. Since this parameter is - * only meaningful in the context of DSA, the above RNG functions + * As per Algorithm 1 of FIPS 186-2 Change Notice 1, in step 3.3 the value + * Xj should be reduced mod q, a 160-bit prime number. Since this parameter + * is only meaningful in the context of DSA, the above RNG functions * were implemented without it. They are re-implemented below for use * with DSA. * */ /* -** Update the global random number generator with more seeding -** material. DSA needs a q parameter. -*/ -SECStatus -DSA_RandomUpdate(void *data, size_t bytes, unsigned char *q) -{ - if( q && (*q == 0) ) { - ++q; - } - return prng_RandomUpdate(globalrng, data, bytes, q); -} - -/* ** Generate some random bytes, using the global random number generator ** object. In DSA mode, so there is a q. */ SECStatus -DSA_GenerateGlobalRandomBytes(void *dest, size_t len, unsigned char *q) +DSA_GenerateGlobalRandomBytes(void *dest, size_t len, const unsigned char *q) { - if( q && (*q == 0) ) { + SECStatus rv; + unsigned char w[2*GSIZE]; + + PORT_Assert(q && len == DSA_SUBPRIME_LEN); + if (len != DSA_SUBPRIME_LEN) { + PORT_SetError(SEC_ERROR_OUTPUT_LEN); + return SECFailure; + } + if (*q == 0) { ++q; } - return prng_GenerateGlobalRandomBytes(globalrng, dest, len, q); + rv = prng_GenerateGlobalRandomBytes(globalrng, w, 2*GSIZE); + if (rv != SECSuccess) { + return rv; + } + dsa_reduce_mod_q(w, q, (unsigned char *)dest); + return rv; } diff --git a/security/nss/lib/softoken/rawhash.c b/security/nss/lib/freebl/rawhash.c index 7757cebbd..a3efe9b30 100644 --- a/security/nss/lib/softoken/rawhash.c +++ b/security/nss/lib/freebl/rawhash.c @@ -37,7 +37,7 @@ #include "nspr.h" #include "sechash.h" #include "blapi.h" /* below the line */ - +#include "secerr.h" static void * null_hash_new_context(void) @@ -84,7 +84,9 @@ const SECHashObject SECRawHashObjects[] = { (void (*)(void *)) null_hash_begin, (void (*)(void *, const unsigned char *, unsigned int)) null_hash_update, (void (*)(void *, unsigned char *, unsigned int *, - unsigned int)) null_hash_end + unsigned int)) null_hash_end, + 0, + HASH_AlgNULL }, { MD2_LENGTH, (void * (*)(void)) MD2_NewContext, @@ -92,7 +94,9 @@ const SECHashObject SECRawHashObjects[] = { (void (*)(void *, PRBool)) MD2_DestroyContext, (void (*)(void *)) MD2_Begin, (void (*)(void *, const unsigned char *, unsigned int)) MD2_Update, - (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) MD2_End + (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) MD2_End, + MD2_BLOCK_LENGTH, + HASH_AlgMD2 }, { MD5_LENGTH, (void * (*)(void)) MD5_NewContext, @@ -100,7 +104,9 @@ const SECHashObject SECRawHashObjects[] = { (void (*)(void *, PRBool)) MD5_DestroyContext, (void (*)(void *)) MD5_Begin, (void (*)(void *, const unsigned char *, unsigned int)) MD5_Update, - (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) MD5_End + (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) MD5_End, + MD5_BLOCK_LENGTH, + HASH_AlgMD5 }, { SHA1_LENGTH, (void * (*)(void)) SHA1_NewContext, @@ -108,7 +114,9 @@ const SECHashObject SECRawHashObjects[] = { (void (*)(void *, PRBool)) SHA1_DestroyContext, (void (*)(void *)) SHA1_Begin, (void (*)(void *, const unsigned char *, unsigned int)) SHA1_Update, - (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) SHA1_End + (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) SHA1_End, + SHA1_BLOCK_LENGTH, + HASH_AlgSHA1 }, { SHA256_LENGTH, (void * (*)(void)) SHA256_NewContext, @@ -116,7 +124,10 @@ const SECHashObject SECRawHashObjects[] = { (void (*)(void *, PRBool)) SHA256_DestroyContext, (void (*)(void *)) SHA256_Begin, (void (*)(void *, const unsigned char *, unsigned int)) SHA256_Update, - (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) SHA256_End + (void (*)(void *, unsigned char *, unsigned int *, + unsigned int)) SHA256_End, + SHA256_BLOCK_LENGTH, + HASH_AlgSHA256 }, { SHA384_LENGTH, (void * (*)(void)) SHA384_NewContext, @@ -124,7 +135,10 @@ const SECHashObject SECRawHashObjects[] = { (void (*)(void *, PRBool)) SHA384_DestroyContext, (void (*)(void *)) SHA384_Begin, (void (*)(void *, const unsigned char *, unsigned int)) SHA384_Update, - (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) SHA384_End + (void (*)(void *, unsigned char *, unsigned int *, + unsigned int)) SHA384_End, + SHA384_BLOCK_LENGTH, + HASH_AlgSHA384 }, { SHA512_LENGTH, (void * (*)(void)) SHA512_NewContext, @@ -132,7 +146,19 @@ const SECHashObject SECRawHashObjects[] = { (void (*)(void *, PRBool)) SHA512_DestroyContext, (void (*)(void *)) SHA512_Begin, (void (*)(void *, const unsigned char *, unsigned int)) SHA512_Update, - (void (*)(void *, unsigned char *, unsigned int *, unsigned int)) SHA512_End + (void (*)(void *, unsigned char *, unsigned int *, + unsigned int)) SHA512_End, + SHA512_BLOCK_LENGTH, + HASH_AlgSHA512 }, }; +const SECHashObject * +HASH_GetRawHashObject(HASH_HashType hashType) +{ + if (hashType < HASH_AlgNULL || hashType >= HASH_AlgTOTAL) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return NULL; + } + return &SECRawHashObjects[hashType]; +} diff --git a/security/nss/lib/util/ret_cr16.s b/security/nss/lib/freebl/ret_cr16.s index d1fffc577..d1fffc577 100644 --- a/security/nss/lib/util/ret_cr16.s +++ b/security/nss/lib/freebl/ret_cr16.s diff --git a/security/nss/lib/freebl/rijndael.c b/security/nss/lib/freebl/rijndael.c index 569500408..58f5e5cdf 100644 --- a/security/nss/lib/freebl/rijndael.c +++ b/security/nss/lib/freebl/rijndael.c @@ -969,16 +969,16 @@ rijndael_decryptCBC(AESContext *cx, unsigned char *output, * ***********************************************************************/ -/* AES_CreateContext - * - * create a new context for Rijndael operations - */ -AESContext * -AES_CreateContext(const unsigned char *key, const unsigned char *iv, - int mode, int encrypt, - unsigned int keysize, unsigned int blocksize) +AESContext * AES_AllocateContext(void) +{ + return PORT_ZNew(AESContext); +} + +SECStatus +AES_InitContext(AESContext *cx, const unsigned char *key, unsigned int keysize, + const unsigned char *iv, int mode, unsigned int encrypt, + unsigned int blocksize) { - AESContext *cx; unsigned int Nk; /* According to Rijndael AES Proposal, section 12.1, block and key * lengths between 128 and 256 bits are supported, as long as the @@ -992,20 +992,19 @@ AES_CreateContext(const unsigned char *key, const unsigned char *iv, blocksize > RIJNDAEL_MAX_BLOCKSIZE || blocksize % 4 != 0) { PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; + return SECFailure; } if (mode != NSS_AES && mode != NSS_AES_CBC) { PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; + return SECFailure; } if (mode == NSS_AES_CBC && iv == NULL) { PORT_SetError(SEC_ERROR_INVALID_ARGS); - return NULL; + return SECFailure; } - cx = PORT_ZNew(AESContext); if (!cx) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return NULL; + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; } /* Nb = (block size in bits) / 32 */ cx->Nb = blocksize / 4; @@ -1020,10 +1019,9 @@ AES_CreateContext(const unsigned char *key, const unsigned char *iv, } else { cx->worker = (encrypt) ? &rijndael_encryptECB : &rijndael_decryptECB; } - /* Allocate memory for the expanded key */ - cx->expandedKey = PORT_ZNewArray(PRUint32, cx->Nb * (cx->Nr + 1)); - if (!cx->expandedKey) { - PORT_SetError(SEC_ERROR_NO_MEMORY); + PORT_Assert((cx->Nb * (cx->Nr + 1)) <= RIJNDAEL_MAX_EXP_KEY_SIZE); + if ((cx->Nb * (cx->Nr + 1)) > RIJNDAEL_MAX_EXP_KEY_SIZE) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); goto cleanup; } /* Generate expanded key */ @@ -1034,12 +1032,31 @@ AES_CreateContext(const unsigned char *key, const unsigned char *iv, if (rijndael_invkey_expansion(cx, key, Nk) != SECSuccess) goto cleanup; } - return cx; + return SECSuccess; cleanup: - if (cx->expandedKey) - PORT_ZFree(cx->expandedKey, cx->Nb * (cx->Nr + 1)); - PORT_ZFree(cx, sizeof *cx); - return NULL; + return SECFailure; +} + + +/* AES_CreateContext + * + * create a new context for Rijndael operations + */ +AESContext * +AES_CreateContext(const unsigned char *key, const unsigned char *iv, + int mode, int encrypt, + unsigned int keysize, unsigned int blocksize) +{ + AESContext *cx = AES_AllocateContext(); + if (cx) { + SECStatus rv = AES_InitContext(cx, key, keysize, iv, mode, encrypt, + blocksize); + if (rv != SECSuccess) { + AES_DestroyContext(cx, PR_TRUE); + cx = NULL; + } + } + return cx; } /* @@ -1051,8 +1068,7 @@ cleanup: void AES_DestroyContext(AESContext *cx, PRBool freeit) { - PORT_ZFree(cx->expandedKey, cx->Nb * (cx->Nr + 1)); - memset(cx, 0, sizeof *cx); +/* memset(cx, 0, sizeof *cx); */ if (freeit) PORT_Free(cx); } diff --git a/security/nss/lib/freebl/rijndael.h b/security/nss/lib/freebl/rijndael.h index 71a3a7768..4ace67528 100644 --- a/security/nss/lib/freebl/rijndael.h +++ b/security/nss/lib/freebl/rijndael.h @@ -50,6 +50,29 @@ typedef SECStatus AESBlockFunc(AESContext *cx, unsigned char *output, const unsigned char *input); +/* RIJNDAEL_NUM_ROUNDS + * + * Number of rounds per execution + * Nk - number of key bytes + * Nb - blocksize (in bytes) + */ +#define RIJNDAEL_NUM_ROUNDS(Nk, Nb) \ + (PR_MAX(Nk, Nb) + 6) + +/* RIJNDAEL_MAX_STATE_SIZE + * + * Maximum number of bytes in the state (spec includes up to 256-bit block + * size) + */ +#define RIJNDAEL_MAX_STATE_SIZE 32 + +/* + * This magic number is (Nb_max * (Nr_max + 1)) + * where Nb_max is the maximum block size in 32-bit words, + * Nr_max is the maximum number of rounds, which is Nb_max + 6 + */ +#define RIJNDAEL_MAX_EXP_KEY_SIZE (8 * 15) + /* AESContextStr * * Values which maintain the state for Rijndael encryption/decryption. @@ -64,25 +87,9 @@ struct AESContextStr { unsigned int Nb; unsigned int Nr; - PRUint32 *expandedKey; AESFunc *worker; unsigned char iv[RIJNDAEL_MAX_BLOCKSIZE]; + PRUint32 expandedKey[RIJNDAEL_MAX_EXP_KEY_SIZE]; }; -/* RIJNDAEL_NUM_ROUNDS - * - * Number of rounds per execution - * Nk - number of key bytes - * Nb - blocksize (in bytes) - */ -#define RIJNDAEL_NUM_ROUNDS(Nk, Nb) \ - (PR_MAX(Nk, Nb) + 6) - -/* RIJNDAEL_NUM_ROUNDS - * - * Maximum number of bytes in the state (spec includes up to 256-bit block - * size) - */ -#define RIJNDAEL_MAX_STATE_SIZE 32 - #endif /* _RIJNDAEL_H_ */ diff --git a/security/nss/lib/freebl/secmpi.h b/security/nss/lib/freebl/secmpi.h index 6b7a926b7..e343fb894 100644 --- a/security/nss/lib/freebl/secmpi.h +++ b/security/nss/lib/freebl/secmpi.h @@ -48,6 +48,7 @@ #define MPINT_TO_SECITEM(mp, it, arena) \ SECITEM_AllocItem(arena, (it), mp_unsigned_octet_size(mp)); \ + if ((it)->data == NULL) {err = MP_MEM; goto cleanup;} \ err = mp_to_unsigned_octets(mp, (it)->data, (it)->len); \ if (err < 0) goto cleanup; else err = MP_OKAY; diff --git a/security/nss/lib/freebl/sha-fast-amd64-sun.s b/security/nss/lib/freebl/sha-fast-amd64-sun.s new file mode 100644 index 000000000..7c43f554b --- /dev/null +++ b/security/nss/lib/freebl/sha-fast-amd64-sun.s @@ -0,0 +1,2142 @@ +//* ***** BEGIN LICENSE BLOCK ***** +/ * Version: MPL 1.1/GPL 2.0/LGPL 2.1 +/ * +/ * The contents of this file are subject to the Mozilla Public License Version +/ * 1.1 (the "License"); you may not use this file except in compliance with +/ * the License. You may obtain a copy of the License at +/ * http://www.mozilla.org/MPL/ +/ * +/ * Software distributed under the License is distributed on an "AS IS" basis, +/ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +/ * for the specific language governing rights and limitations under the +/ * License. +/ * +/ * The Original Code is SHA 180-1 Reference Implementation (Optimized). +/ * +/ * The Initial Developer of the Original Code is +/ * Paul Kocher of Cryptography Research. +/ * Portions created by the Initial Developer are Copyright (C) 1995-9 +/ * the Initial Developer. All Rights Reserved. +/ * +/ * Contributor(s): +/ * +/ * Alternatively, the contents of this file may be used under the terms of +/ * either the GNU General Public License Version 2 or later (the "GPL"), or +/ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +/ * in which case the provisions of the GPL or the LGPL are applicable instead +/ * of those above. If you wish to allow use of your version of this file only +/ * under the terms of either the GPL or the LGPL, and not to allow others to +/ * use your version of this file under the terms of the MPL, indicate your +/ * decision by deleting the provisions above and replace them with the notice +/ * and other provisions required by the GPL or the LGPL. If you do not delete +/ * the provisions above, a recipient may use your version of this file under +/ * the terms of any one of the MPL, the GPL or the LGPL. +/ * +/ * ***** END LICENSE BLOCK ***** */ + + .file "sha_fast.c" + .text + .align 16 +.globl SHA1_Begin + .type SHA1_Begin, @function +SHA1_Begin: +.LFB4: + movl $4023233417, %ecx + movl $2562383102, %edx + movl $3285377520, %eax + movq $0, 64(%rdi) + movq $1732584193, 72(%rdi) + movq %rcx, 80(%rdi) + movq %rdx, 88(%rdi) + movq $271733878, 96(%rdi) + movq %rax, 104(%rdi) + ret +.LFE4: + .size SHA1_Begin, .-SHA1_Begin + .align 16 + .type shaCompress, @function +shaCompress: +.LFB7: + pushq %r15 +.LCFI0: + pushq %r14 +.LCFI1: + pushq %r13 +.LCFI2: + pushq %r12 +.LCFI3: + movq -88(%rdi), %r12 + movq -80(%rdi), %r10 + movq -72(%rdi), %r13 + movq -64(%rdi), %r8 + pushq %rbx +.LCFI4: + movq -56(%rdi), %rcx + movl (%rsi), %eax + movl %r12d, %edx + movq %r13, %r9 + roll $5, %edx + movl 4(%rsi), %ebx + xorq %r8, %r9 +/APP + bswap %eax +/NO_APP + andq %r10, %r9 + mov %eax, %r15d + roll $30, %r10d + movq %r15, -48(%rdi) + xorq %r8, %r9 + movq -48(%rdi), %r14 + addq %r9, %rdx + movq %r10, %rax + movl %r12d, %r15d + addq %rcx, %rdx + xorq %r13, %rax + roll $30, %r15d + leaq 1518500249(%rdx,%r14), %rdx + andq %r12, %rax + movq %r15, %r12 +/APP + bswap %ebx +/NO_APP + movl %edx, %ecx + mov %ebx, %r11d + xorq %r13, %rax + movq %r11, -40(%rdi) + roll $5, %ecx + movq -40(%rdi), %r9 + addq %rax, %rcx + xorq %r10, %r12 + movl 8(%rsi), %r14d + addq %r8, %rcx + andq %rdx, %r12 + movl %edx, %r11d + leaq 1518500249(%rcx,%r9), %rcx + xorq %r10, %r12 + roll $30, %r11d +/APP + bswap %r14d +/NO_APP + movl %ecx, %r8d + mov %r14d, %ebx + movl 12(%rsi), %r9d + movq %rbx, -32(%rdi) + roll $5, %r8d + movq -32(%rdi), %rax + addq %r12, %r8 + movq %r11, %r12 + movl %ecx, %ebx + addq %r13, %r8 + xorq %r15, %r12 + roll $30, %ebx + leaq 1518500249(%r8,%rax), %r8 + andq %rcx, %r12 + movl 16(%rsi), %eax +/APP + bswap %r9d +/NO_APP + movl %r8d, %edx + mov %r9d, %r14d + xorq %r15, %r12 + movq %r14, -24(%rdi) + roll $5, %edx + movq -24(%rdi), %r13 + addq %r12, %rdx + movq %rbx, %r12 + movl %r8d, %r14d + addq %r10, %rdx + leaq 1518500249(%rdx,%r13), %rdx + movl 20(%rsi), %r13d +/APP + bswap %eax +/NO_APP + movl %edx, %ecx + mov %eax, %r9d + roll $5, %ecx + xorq %r11, %r12 + movq %r9, -16(%rdi) + andq %r8, %r12 + movq -16(%rdi), %r10 + roll $30, %r14d + xorq %r11, %r12 + movq %r14, %rax + movl %edx, %r9d + addq %r12, %rcx + xorq %rbx, %rax + roll $30, %r9d + addq %r15, %rcx + andq %rdx, %rax + leaq 1518500249(%rcx,%r10), %rcx + xorq %rbx, %rax + movl 24(%rsi), %r10d +/APP + bswap %r13d +/NO_APP + movl %ecx, %r8d + mov %r13d, %r15d + movq %r15, -8(%rdi) + roll $5, %r8d + movq -8(%rdi), %r12 + addq %rax, %r8 + movl %ecx, %r15d + addq %r11, %r8 + movq %r9, %r11 + roll $30, %r15d + leaq 1518500249(%r8,%r12), %r8 + xorq %r14, %r11 + movl 28(%rsi), %r12d +/APP + bswap %r10d +/NO_APP + andq %rcx, %r11 + mov %r10d, %r13d + movl %r8d, %edx + movq %r13, (%rdi) + xorq %r14, %r11 + movq (%rdi), %rax + roll $5, %edx + movq %r15, %r10 + movl %r8d, %r13d + addq %r11, %rdx + xorq %r9, %r10 + roll $30, %r13d + addq %rbx, %rdx + andq %r8, %r10 + leaq 1518500249(%rdx,%rax), %rdx + xorq %r9, %r10 + movl 32(%rsi), %eax +/APP + bswap %r12d +/NO_APP + movl %edx, %ecx + mov %r12d, %ebx + movq %rbx, 8(%rdi) + roll $5, %ecx + movq 8(%rdi), %r11 + addq %r10, %rcx + movq %r13, %r10 + movl %edx, %ebx + addq %r14, %rcx + leaq 1518500249(%rcx,%r11), %rcx +/APP + bswap %eax +/NO_APP + movl %ecx, %r8d + mov %eax, %r12d + roll $5, %r8d + xorq %r15, %r10 + movq %r12, 16(%rdi) + andq %rdx, %r10 + movq 16(%rdi), %r14 + roll $30, %ebx + xorq %r15, %r10 + movq %rbx, %rax + movl 36(%rsi), %r11d + addq %r10, %r8 + xorq %r13, %rax + movl %ecx, %r12d + addq %r9, %r8 + andq %rcx, %rax + roll $30, %r12d + leaq 1518500249(%r8,%r14), %r8 + xorq %r13, %rax + movl 40(%rsi), %r14d +/APP + bswap %r11d +/NO_APP + movl %r8d, %edx + mov %r11d, %r9d + movq %r12, %r11 + movq %r9, 24(%rdi) + roll $5, %edx + movq 24(%rdi), %r10 + addq %rax, %rdx + xorq %rbx, %r11 + movl %r8d, %r9d + addq %r15, %rdx + andq %r8, %r11 + roll $30, %r9d + leaq 1518500249(%rdx,%r10), %rdx + xorq %rbx, %r11 + movl 44(%rsi), %r10d +/APP + bswap %r14d +/NO_APP + movl %edx, %ecx + mov %r14d, %r15d + movq %r15, 32(%rdi) + roll $5, %ecx + movq 32(%rdi), %rax + addq %r11, %rcx + movq %r9, %r11 + movl %edx, %r15d + addq %r13, %rcx + xorq %r12, %r11 + roll $30, %r15d + leaq 1518500249(%rcx,%rax), %rcx + andq %rdx, %r11 + movl 48(%rsi), %eax +/APP + bswap %r10d +/NO_APP + movl %ecx, %r8d + mov %r10d, %r14d + xorq %r12, %r11 + movq %r14, 40(%rdi) + roll $5, %r8d + movq 40(%rdi), %r13 + addq %r11, %r8 + movq %r15, %r10 + movl %ecx, %r14d + addq %rbx, %r8 + xorq %r9, %r10 + leaq 1518500249(%r8,%r13), %r8 + movl 52(%rsi), %r13d +/APP + bswap %eax +/NO_APP + movl %r8d, %edx + mov %eax, %ebx + roll $5, %edx + andq %rcx, %r10 + movq %rbx, 48(%rdi) + xorq %r9, %r10 + movq 48(%rdi), %r11 + roll $30, %r14d + addq %r10, %rdx + movq %r14, %rax + movl %r8d, %ebx + addq %r12, %rdx + xorq %r15, %rax + roll $30, %ebx + leaq 1518500249(%rdx,%r11), %rdx + andq %r8, %rax + movl 56(%rsi), %r11d +/APP + bswap %r13d +/NO_APP + movl %edx, %ecx + mov %r13d, %r12d + xorq %r15, %rax + movq %r12, 56(%rdi) + roll $5, %ecx + movq 56(%rdi), %r10 + addq %rax, %rcx + movl %edx, %r12d + addq %r9, %rcx + movq %rbx, %r9 + roll $30, %r12d + leaq 1518500249(%rcx,%r10), %rcx + xorq %r14, %r9 + movl 60(%rsi), %r10d +/APP + bswap %r11d +/NO_APP + andq %rdx, %r9 + mov %r11d, %r13d + movl %ecx, %r8d + movq %r13, 64(%rdi) + xorq %r14, %r9 + movq 64(%rdi), %rax + roll $5, %r8d + movq %r12, %r11 + movl %ecx, %r13d + addq %r9, %r8 + xorq %rbx, %r11 + roll $30, %r13d + addq %r15, %r8 + andq %rcx, %r11 + leaq 1518500249(%r8,%rax), %r8 + xorq %rbx, %r11 +/APP + bswap %r10d +/NO_APP + movl %r8d, %esi + mov %r10d, %r15d + movq %r15, 72(%rdi) + roll $5, %esi + movq 72(%rdi), %r9 + movq 56(%rdi), %r10 + movq 16(%rdi), %rcx + addq %r11, %rsi + movq -32(%rdi), %rdx + addq %r14, %rsi + movq -48(%rdi), %rax + leaq 1518500249(%rsi,%r9), %r14 + movq %r13, %r11 + movl %r8d, %r15d + xorq %rcx, %r10 + xorq %rdx, %r10 + movl %r14d, %ecx + xorl %eax, %r10d + roll %r10d + roll $5, %ecx + xorq %r12, %r11 + andq %r8, %r11 + movq %r10, -48(%rdi) + movq -48(%rdi), %r9 + xorq %r12, %r11 + roll $30, %r15d + movl %r14d, %r10d + addq %r11, %rcx + movq 64(%rdi), %r11 + movq 24(%rdi), %rdx + addq %rbx, %rcx + movq -24(%rdi), %rbx + movq -40(%rdi), %rax + leaq 1518500249(%rcx,%r9), %rcx + movq %r15, %r8 + roll $30, %r10d + xorq %rdx, %r11 + xorq %r13, %r8 + xorq %rbx, %r11 + andq %r14, %r8 + movl %ecx, %r9d + xorl %eax, %r11d + xorq %r13, %r8 + roll $5, %r9d + roll %r11d + addq %r8, %r9 + movq %r10, %rax + movq %r11, -40(%rdi) + movq -40(%rdi), %rsi + addq %r12, %r9 + movq 72(%rdi), %rbx + movq 32(%rdi), %rdx + xorq %r15, %rax + movq -16(%rdi), %r14 + movq -32(%rdi), %r12 + andq %rcx, %rax + leaq 1518500249(%r9,%rsi), %r9 + xorq %r15, %rax + movl %ecx, %r11d + xorq %rdx, %rbx + roll $30, %r11d + xorq %r14, %rbx + movl %r9d, %esi + xorl %r12d, %ebx + roll $5, %esi + roll %ebx + addq %rax, %rsi + movq %rbx, -32(%rdi) + movq -32(%rdi), %r8 + addq %r13, %rsi + movq -48(%rdi), %r12 + movq 40(%rdi), %rdx + movq %r11, %r13 + movq -8(%rdi), %r14 + movq -24(%rdi), %rcx + movl %r9d, %ebx + leaq 1518500249(%rsi,%r8), %rsi + xorq %rdx, %r12 + xorq %r14, %r12 + movl %esi, %r8d + xorl %ecx, %r12d + roll %r12d + roll $5, %r8d + xorq %r10, %r13 + andq %r9, %r13 + movq %r12, -24(%rdi) + movq -24(%rdi), %rax + xorq %r10, %r13 + roll $30, %ebx + movl %esi, %r12d + addq %r13, %r8 + xorq %rbx, %rsi + roll $30, %r12d + addq %r15, %r8 + movq -40(%rdi), %r15 + movq 48(%rdi), %rdx + movq (%rdi), %r14 + movq -16(%rdi), %r9 + leaq 1518500249(%r8,%rax), %r13 + xorq %r11, %rsi + xorq %rdx, %r15 + movl %r13d, %ecx + xorq %r14, %r15 + roll $5, %ecx + xorl %r9d, %r15d + addq %rsi, %rcx + roll %r15d + addq %r10, %rcx + movq %r15, -16(%rdi) + movq -16(%rdi), %rsi + movl %r13d, %r15d + movq -32(%rdi), %r14 + movq 56(%rdi), %rax + xorq %r12, %r13 + movq 8(%rdi), %rdx + movq -8(%rdi), %r10 + xorq %rbx, %r13 + leaq 1859775393(%rcx,%rsi), %r9 + roll $30, %r15d + xorq %rax, %r14 + xorq %rdx, %r14 + movl %r9d, %esi + xorl %r10d, %r14d + roll $5, %esi + roll %r14d + addq %r13, %rsi + movq %r14, -8(%rdi) + movq -8(%rdi), %r8 + addq %r11, %rsi + movq -24(%rdi), %r13 + movq 64(%rdi), %rax + movl %r9d, %r14d + movq 16(%rdi), %rdx + movq (%rdi), %r11 + xorq %r15, %r9 + leaq 1859775393(%rsi,%r8), %r10 + xorq %rax, %r13 + xorq %rdx, %r13 + movl %r10d, %r8d + xorl %r11d, %r13d + roll $5, %r8d + roll %r13d + xorq %r12, %r9 + roll $30, %r14d + addq %r9, %r8 + movq %r13, (%rdi) + movq (%rdi), %rcx + addq %rbx, %r8 + movq -16(%rdi), %rbx + movq 72(%rdi), %rax + movq 24(%rdi), %rdx + movq 8(%rdi), %r9 + movl %r10d, %r13d + leaq 1859775393(%r8,%rcx), %r11 + xorq %r14, %r10 + roll $30, %r13d + xorq %rax, %rbx + xorq %r15, %r10 + xorq %rdx, %rbx + movl %r11d, %ecx + xorl %r9d, %ebx + roll $5, %ecx + roll %ebx + addq %r10, %rcx + movq %rbx, 8(%rdi) + movq 8(%rdi), %rsi + addq %r12, %rcx + movq -8(%rdi), %r12 + movq -48(%rdi), %rax + movl %r11d, %ebx + movq 32(%rdi), %rdx + movq 16(%rdi), %r9 + xorq %r13, %r11 + leaq 1859775393(%rcx,%rsi), %r10 + xorq %r14, %r11 + roll $30, %ebx + xorq %rax, %r12 + xorq %rdx, %r12 + movl %r10d, %esi + xorl %r9d, %r12d + roll $5, %esi + roll %r12d + addq %r11, %rsi + movq %r12, 16(%rdi) + addq %r15, %rsi + movq 16(%rdi), %r8 + movq (%rdi), %r15 + movq -40(%rdi), %rax + movl %r10d, %r12d + movq 40(%rdi), %rdx + movq 24(%rdi), %r9 + xorq %rbx, %r10 + leaq 1859775393(%rsi,%r8), %r11 + xorq %r13, %r10 + xorq %rax, %r15 + xorq %rdx, %r15 + movl %r11d, %r8d + xorl %r9d, %r15d + roll $5, %r8d + roll %r15d + addq %r10, %r8 + movq %r15, 24(%rdi) + movq 24(%rdi), %rcx + addq %r14, %r8 + movq 8(%rdi), %r14 + movq -32(%rdi), %rax + roll $30, %r12d + movq 48(%rdi), %rdx + movq 32(%rdi), %r10 + movl %r11d, %r15d + leaq 1859775393(%r8,%rcx), %r9 + xorq %r12, %r11 + roll $30, %r15d + xorq %rax, %r14 + xorq %rbx, %r11 + xorq %rdx, %r14 + movl %r9d, %ecx + xorl %r10d, %r14d + roll $5, %ecx + roll %r14d + addq %r11, %rcx + movq %r14, 32(%rdi) + addq %r13, %rcx + movq 32(%rdi), %rsi + movq 16(%rdi), %r13 + movq -24(%rdi), %rax + movl %r9d, %r14d + movq 56(%rdi), %rdx + movq 40(%rdi), %r11 + xorq %r15, %r9 + leaq 1859775393(%rcx,%rsi), %r10 + xorq %r12, %r9 + roll $30, %r14d + xorq %rax, %r13 + xorq %rdx, %r13 + movl %r10d, %esi + xorl %r11d, %r13d + roll $5, %esi + roll %r13d + addq %r9, %rsi + movq %r13, 40(%rdi) + movq 40(%rdi), %r8 + addq %rbx, %rsi + movq 24(%rdi), %rbx + movq -16(%rdi), %rax + movl %r10d, %r13d + movq 64(%rdi), %rdx + movq 48(%rdi), %r9 + xorq %r14, %r10 + leaq 1859775393(%rsi,%r8), %r11 + xorq %r15, %r10 + roll $30, %r13d + xorq %rax, %rbx + xorq %rdx, %rbx + movl %r11d, %r8d + xorl %r9d, %ebx + roll $5, %r8d + roll %ebx + addq %r10, %r8 + movq %rbx, 48(%rdi) + addq %r12, %r8 + movq 48(%rdi), %rcx + movq 32(%rdi), %r12 + movq -8(%rdi), %rax + movl %r11d, %ebx + movq 72(%rdi), %rdx + movq 56(%rdi), %r9 + leaq 1859775393(%r8,%rcx), %r10 + xorq %rax, %r12 + xorq %rdx, %r12 + movl %r10d, %ecx + xorl %r9d, %r12d + xorq %r13, %r11 + roll $5, %ecx + xorq %r14, %r11 + roll %r12d + roll $30, %ebx + addq %r11, %rcx + movq %r12, 56(%rdi) + movq 56(%rdi), %rsi + addq %r15, %rcx + movq 40(%rdi), %r15 + movq (%rdi), %rax + movq -48(%rdi), %rdx + movq 64(%rdi), %r9 + movl %r10d, %r12d + leaq 1859775393(%rcx,%rsi), %r11 + xorq %rbx, %r10 + roll $30, %r12d + xorq %rax, %r15 + xorq %r13, %r10 + xorq %rdx, %r15 + movl %r11d, %esi + xorl %r9d, %r15d + roll $5, %esi + roll %r15d + addq %r10, %rsi + movq %r15, 64(%rdi) + movq 64(%rdi), %r8 + addq %r14, %rsi + movq 48(%rdi), %r14 + movq 8(%rdi), %rax + movl %r11d, %r15d + movq -40(%rdi), %rdx + movq 72(%rdi), %r10 + xorq %r12, %r11 + leaq 1859775393(%rsi,%r8), %r9 + xorq %rbx, %r11 + roll $30, %r15d + xorq %rax, %r14 + xorq %rdx, %r14 + movl %r9d, %r8d + xorl %r10d, %r14d + roll $5, %r8d + roll %r14d + addq %r11, %r8 + movq %r14, 72(%rdi) + addq %r13, %r8 + movq 72(%rdi), %rcx + movq 56(%rdi), %r13 + movq 16(%rdi), %rax + movl %r9d, %r14d + movq -32(%rdi), %rdx + movq -48(%rdi), %r11 + leaq 1859775393(%r8,%rcx), %r10 + xorq %rax, %r13 + xorq %rdx, %r13 + movl %r10d, %ecx + xorl %r11d, %r13d + roll $5, %ecx + roll %r13d + xorq %r15, %r9 + roll $30, %r14d + xorq %r12, %r9 + movq %r13, -48(%rdi) + movq -48(%rdi), %rsi + addq %r9, %rcx + movl %r10d, %r13d + xorq %r14, %r10 + addq %rbx, %rcx + movq 64(%rdi), %rbx + movq 24(%rdi), %rax + movq -24(%rdi), %rdx + leaq 1859775393(%rcx,%rsi), %r11 + movq -40(%rdi), %r9 + xorq %r15, %r10 + roll $30, %r13d + xorq %rax, %rbx + movl %r11d, %esi + xorq %rdx, %rbx + roll $5, %esi + xorl %r9d, %ebx + addq %r10, %rsi + roll %ebx + addq %r12, %rsi + movq %rbx, -40(%rdi) + movq -40(%rdi), %r8 + movl %r11d, %ebx + movq 72(%rdi), %r12 + movq 32(%rdi), %rax + xorq %r13, %r11 + movq -16(%rdi), %rdx + movq -32(%rdi), %r9 + xorq %r14, %r11 + leaq 1859775393(%rsi,%r8), %r10 + roll $30, %ebx + xorq %rax, %r12 + xorq %rdx, %r12 + movl %r10d, %r8d + xorl %r9d, %r12d + roll $5, %r8d + roll %r12d + addq %r11, %r8 + movq %r12, -32(%rdi) + movq -32(%rdi), %rcx + addq %r15, %r8 + movq -48(%rdi), %r15 + movq 40(%rdi), %rax + movl %r10d, %r12d + movq -8(%rdi), %rdx + movq -24(%rdi), %r9 + xorq %rbx, %r10 + leaq 1859775393(%r8,%rcx), %r11 + xorq %r13, %r10 + xorq %rax, %r15 + xorq %rdx, %r15 + movl %r11d, %ecx + xorl %r9d, %r15d + roll $5, %ecx + roll %r15d + addq %r10, %rcx + addq %r14, %rcx + movq %r15, -24(%rdi) + movq -24(%rdi), %rsi + movq -40(%rdi), %r14 + movq 48(%rdi), %rax + roll $30, %r12d + movq (%rdi), %rdx + movq -16(%rdi), %r10 + movl %r11d, %r15d + leaq 1859775393(%rcx,%rsi), %r9 + xorq %r12, %r11 + roll $30, %r15d + xorq %rax, %r14 + xorq %rbx, %r11 + xorq %rdx, %r14 + movl %r9d, %esi + xorl %r10d, %r14d + roll $5, %esi + roll %r14d + addq %r11, %rsi + movq %r14, -16(%rdi) + movq -16(%rdi), %r8 + addq %r13, %rsi + movq -32(%rdi), %r11 + movq 56(%rdi), %rax + movl %r9d, %r14d + movq 8(%rdi), %rdx + movq -8(%rdi), %r10 + xorq %r15, %r9 + leaq 1859775393(%rsi,%r8), %r13 + xorq %r12, %r9 + roll $30, %r14d + xorq %rax, %r11 + xorq %rdx, %r11 + movl %r13d, %r8d + xorl %r10d, %r11d + roll $5, %r8d + movl %r13d, %r10d + roll %r11d + addq %r9, %r8 + xorq %r14, %r13 + movq %r11, -8(%rdi) + addq %rbx, %r8 + movq -8(%rdi), %rbx + movq -24(%rdi), %r9 + movq 64(%rdi), %rax + xorq %r15, %r13 + movq 16(%rdi), %rdx + movq (%rdi), %rcx + leaq 1859775393(%r8,%rbx), %r11 + xorq %rax, %r9 + xorq %rdx, %r9 + movl %r11d, %ebx + xorl %ecx, %r9d + roll $5, %ebx + roll %r9d + addq %r13, %rbx + movq %r9, (%rdi) + movq (%rdi), %rsi + addq %r12, %rbx + movq -16(%rdi), %r12 + movq 72(%rdi), %r13 + movl %r11d, %r9d + leaq 1859775393(%rbx,%rsi), %rcx + movl %r10d, %ebx + movq 24(%rdi), %r10 + movq 8(%rdi), %rax + xorq %r13, %r12 + roll $30, %ebx + movl %ecx, %esi + xorq %r10, %r12 + xorq %rbx, %r11 + roll $5, %esi + xorl %eax, %r12d + xorq %r14, %r11 + roll $30, %r9d + roll %r12d + addq %r11, %rsi + movq %rcx, %rax + movq %r12, 8(%rdi) + movq 8(%rdi), %rdx + addq %r15, %rsi + movq -8(%rdi), %r11 + movq -48(%rdi), %r13 + movl %ecx, %r12d + movq 32(%rdi), %r10 + movq 16(%rdi), %r8 + orq %r9, %rcx + leaq 1859775393(%rsi,%rdx), %rsi + andq %rbx, %rcx + andq %r9, %rax + xorq %r13, %r11 + orq %rcx, %rax + roll $30, %r12d + xorq %r10, %r11 + movq %rsi, %r10 + xorl %r8d, %r11d + movl %esi, %r8d + andq %r12, %r10 + roll %r11d + roll $5, %r8d + movq %r11, 16(%rdi) + addq %rax, %r8 + movq 16(%rdi), %r15 + movq (%rdi), %r13 + movq -40(%rdi), %rdx + addq %r14, %r8 + movq 40(%rdi), %r14 + movq 24(%rdi), %rcx + movl %esi, %r11d + addq %r15, %r8 + movl $2400959708, %r15d + orq %r12, %rsi + xorq %rdx, %r13 + addq %r15, %r8 + andq %r9, %rsi + xorq %r14, %r13 + orq %rsi, %r10 + xorl %ecx, %r13d + movl %r8d, %ecx + roll %r13d + roll $5, %ecx + movq %r13, 24(%rdi) + addq %r10, %rcx + movq 24(%rdi), %rax + movq 8(%rdi), %r14 + movq -32(%rdi), %rdx + addq %rbx, %rcx + movq 48(%rdi), %rbx + movq 32(%rdi), %rsi + roll $30, %r11d + addq %rax, %rcx + movl %r8d, %r13d + movq %r8, %r10 + xorq %rdx, %r14 + addq %r15, %rcx + orq %r11, %r8 + xorq %rbx, %r14 + andq %r12, %r8 + andq %r11, %r10 + xorl %esi, %r14d + movl %ecx, %esi + orq %r8, %r10 + roll $5, %esi + roll %r14d + roll $30, %r13d + addq %r10, %rsi + movq %r14, 32(%rdi) + movq 32(%rdi), %rax + addq %r9, %rsi + movq 16(%rdi), %r9 + movq -24(%rdi), %rdx + movq 56(%rdi), %rbx + movq 40(%rdi), %r8 + movl %ecx, %r14d + addq %rax, %rsi + movq %rcx, %r10 + orq %r13, %rcx + xorq %rdx, %r9 + addq %r15, %rsi + andq %r11, %rcx + xorq %rbx, %r9 + andq %r13, %r10 + roll $30, %r14d + xorl %r8d, %r9d + movl %esi, %r8d + orq %rcx, %r10 + roll %r9d + roll $5, %r8d + movq %r9, 40(%rdi) + addq %r10, %r8 + movq 40(%rdi), %rax + movq 24(%rdi), %r10 + movq -16(%rdi), %rdx + addq %r12, %r8 + movq 64(%rdi), %rbx + movq 48(%rdi), %rcx + movl %esi, %r9d + addq %rax, %r8 + movq %rsi, %r12 + xorq %rdx, %r10 + addq %r15, %r8 + xorq %rbx, %r10 + orq %r14, %rsi + andq %r14, %r12 + andq %r13, %rsi + xorl %ecx, %r10d + movl %r8d, %ecx + orq %rsi, %r12 + roll %r10d + roll $5, %ecx + movq %r10, 48(%rdi) + addq %r12, %rcx + movq 48(%rdi), %rax + movq 32(%rdi), %r12 + movq -8(%rdi), %rdx + addq %r11, %rcx + movq 72(%rdi), %rbx + movq 56(%rdi), %rsi + roll $30, %r9d + addq %rax, %rcx + movl %r8d, %r10d + movq %r8, %r11 + xorq %rdx, %r12 + addq %r15, %rcx + orq %r9, %r8 + xorq %rbx, %r12 + andq %r14, %r8 + andq %r9, %r11 + xorl %esi, %r12d + movl %ecx, %esi + orq %r8, %r11 + roll %r12d + roll $5, %esi + roll $30, %r10d + movq %r12, 56(%rdi) + addq %r11, %rsi + movq 56(%rdi), %rax + movq 40(%rdi), %r11 + movq (%rdi), %rdx + addq %r13, %rsi + movq -48(%rdi), %rbx + movq 64(%rdi), %r8 + movq %rcx, %r13 + addq %rax, %rsi + andq %r10, %r13 + movl %ecx, %r12d + xorq %rdx, %r11 + addq %r15, %rsi + xorq %rbx, %r11 + xorl %r8d, %r11d + movl %esi, %r8d + roll %r11d + roll $5, %r8d + orq %r10, %rcx + andq %r9, %rcx + movq %r11, 64(%rdi) + movq 64(%rdi), %rax + orq %rcx, %r13 + roll $30, %r12d + movl %esi, %r11d + addq %r13, %r8 + movq 48(%rdi), %r13 + movq 8(%rdi), %rdx + movq -40(%rdi), %rbx + addq %r14, %r8 + movq 72(%rdi), %rcx + addq %rax, %r8 + movq %rsi, %r14 + orq %r12, %rsi + xorq %rdx, %r13 + addq %r15, %r8 + andq %r10, %rsi + xorq %rbx, %r13 + andq %r12, %r14 + roll $30, %r11d + xorl %ecx, %r13d + movl %r8d, %ecx + orq %rsi, %r14 + roll %r13d + roll $5, %ecx + movq %r13, 72(%rdi) + addq %r14, %rcx + movq 72(%rdi), %rax + movq 56(%rdi), %r14 + movq 16(%rdi), %rdx + addq %r9, %rcx + movq -32(%rdi), %rbx + movq -48(%rdi), %rsi + movl %r8d, %r13d + addq %rax, %rcx + movq %r8, %r9 + orq %r11, %r8 + xorq %rdx, %r14 + addq %r15, %rcx + andq %r12, %r8 + xorq %rbx, %r14 + andq %r11, %r9 + xorl %esi, %r14d + movl %ecx, %esi + orq %r8, %r9 + roll $5, %esi + roll %r14d + addq %r9, %rsi + movq %r14, -48(%rdi) + movq -48(%rdi), %rax + addq %r10, %rsi + movq 64(%rdi), %r10 + movq 24(%rdi), %rdx + movq -24(%rdi), %rbx + movq -40(%rdi), %r8 + movl %ecx, %r14d + addq %rax, %rsi + roll $30, %r13d + movq %rcx, %r9 + xorq %rdx, %r10 + addq %r15, %rsi + orq %r13, %rcx + xorq %rbx, %r10 + andq %r11, %rcx + andq %r13, %r9 + xorl %r8d, %r10d + movl %esi, %r8d + orq %rcx, %r9 + roll $5, %r8d + roll %r10d + roll $30, %r14d + addq %r9, %r8 + movq %r10, -40(%rdi) + movq -40(%rdi), %rax + addq %r12, %r8 + movq 72(%rdi), %r12 + movq 32(%rdi), %rdx + movq -16(%rdi), %rbx + movq -32(%rdi), %rcx + movl %esi, %r10d + addq %rax, %r8 + movq %rsi, %r9 + orq %r14, %rsi + xorq %rdx, %r12 + addq %r15, %r8 + andq %r13, %rsi + xorq %rbx, %r12 + andq %r14, %r9 + roll $30, %r10d + xorl %ecx, %r12d + movl %r8d, %ecx + orq %rsi, %r9 + roll $5, %ecx + roll %r12d + addq %r9, %rcx + movq %r12, -32(%rdi) + movq -32(%rdi), %rax + addq %r11, %rcx + movq -48(%rdi), %r11 + movq 40(%rdi), %rdx + movq -8(%rdi), %rbx + movq -24(%rdi), %rsi + movl %r8d, %r12d + addq %rax, %rcx + movq %r8, %r9 + xorq %rdx, %r11 + addq %r15, %rcx + xorq %rbx, %r11 + xorl %esi, %r11d + orq %r10, %r8 + andq %r10, %r9 + andq %r14, %r8 + movl %ecx, %esi + roll %r11d + orq %r8, %r9 + roll $5, %esi + movq %r11, -24(%rdi) + addq %r9, %rsi + movq -24(%rdi), %rax + roll $30, %r12d + addq %r13, %rsi + movq -40(%rdi), %r13 + movq 48(%rdi), %rdx + movq (%rdi), %rbx + movq -16(%rdi), %r8 + movl %ecx, %r11d + addq %rax, %rsi + movq %rcx, %r9 + orq %r12, %rcx + xorq %rdx, %r13 + addq %r15, %rsi + andq %r10, %rcx + xorq %rbx, %r13 + andq %r12, %r9 + roll $30, %r11d + xorl %r8d, %r13d + movl %esi, %r8d + orq %rcx, %r9 + roll %r13d + roll $5, %r8d + movq %r13, -16(%rdi) + addq %r9, %r8 + movq -16(%rdi), %rax + movq -32(%rdi), %r9 + movq 56(%rdi), %rdx + addq %r14, %r8 + movq 8(%rdi), %rcx + movq -8(%rdi), %rbx + movl %esi, %r13d + addq %rax, %r8 + movq %rsi, %r14 + orq %r11, %rsi + xorq %rdx, %r9 + addq %r15, %r8 + andq %r11, %r14 + xorq %rcx, %r9 + xorl %ebx, %r9d + movl %r8d, %ebx + roll %r9d + roll $5, %ebx + andq %r12, %rsi + orq %rsi, %r14 + movq %r9, -8(%rdi) + movq -8(%rdi), %rax + addq %r14, %rbx + movq -24(%rdi), %r14 + movq 64(%rdi), %rdx + movq 16(%rdi), %rcx + addq %r10, %rbx + movq (%rdi), %rsi + roll $30, %r13d + addq %rax, %rbx + movl %r8d, %r9d + xorq %rdx, %r14 + addq %r15, %rbx + movq %r8, %r10 + xorq %rcx, %r14 + orq %r13, %r8 + andq %r13, %r10 + andq %r11, %r8 + xorl %esi, %r14d + movl %ebx, %esi + orq %r8, %r10 + roll $5, %esi + roll %r14d + addq %r10, %rsi + movq %r14, (%rdi) + movq (%rdi), %rax + addq %r12, %rsi + movq -16(%rdi), %r12 + movq 72(%rdi), %rdx + movq 24(%rdi), %rcx + movq 8(%rdi), %r8 + roll $30, %r9d + addq %rax, %rsi + movl %ebx, %r14d + movq %rbx, %r10 + xorq %rdx, %r12 + addq %r15, %rsi + orq %r9, %rbx + xorq %rcx, %r12 + andq %r13, %rbx + andq %r9, %r10 + xorl %r8d, %r12d + movl %esi, %r8d + orq %rbx, %r10 + roll %r12d + roll $5, %r8d + movq %r12, 8(%rdi) + movq 8(%rdi), %rax + addq %r10, %r8 + movq -8(%rdi), %rbx + movq -48(%rdi), %rdx + addq %r11, %r8 + movq 32(%rdi), %r11 + movq 16(%rdi), %rcx + movl %esi, %r12d + addq %rax, %r8 + movq %rsi, %r10 + addq %r15, %r8 + xorq %rdx, %rbx + roll $30, %r14d + xorq %r11, %rbx + orq %r14, %rsi + andq %r14, %r10 + xorl %ecx, %ebx + andq %r9, %rsi + movl %r8d, %ecx + roll %ebx + orq %rsi, %r10 + roll $5, %ecx + movq %rbx, 16(%rdi) + movq 16(%rdi), %rsi + addq %r10, %rcx + movq (%rdi), %r11 + movq -40(%rdi), %rax + addq %r13, %rcx + movq 40(%rdi), %rdx + movq 24(%rdi), %r13 + roll $30, %r12d + addq %rsi, %rcx + movl %r8d, %ebx + movq %r8, %r10 + xorq %rax, %r11 + addq %r15, %rcx + orq %r12, %r8 + xorq %rdx, %r11 + andq %r14, %r8 + andq %r12, %r10 + xorl %r13d, %r11d + movl %ecx, %r13d + orq %r8, %r10 + roll %r11d + roll $5, %r13d + roll $30, %ebx + movq %r11, 24(%rdi) + addq %r10, %r13 + movq 24(%rdi), %rsi + movq 8(%rdi), %r10 + movq -32(%rdi), %rax + addq %r9, %r13 + movq 48(%rdi), %rdx + movq 32(%rdi), %r8 + movl %ecx, %r11d + addq %rsi, %r13 + movq %rcx, %r9 + xorq %rax, %r10 + addq %r15, %r13 + xorq %rdx, %r10 + xorl %r8d, %r10d + movl %r13d, %r8d + roll %r10d + orq %rbx, %rcx + andq %rbx, %r9 + movq %r10, 32(%rdi) + andq %r12, %rcx + movl %r13d, %r10d + orq %rcx, %r9 + roll $5, %r10d + movq 32(%rdi), %rsi + addq %r9, %r10 + roll $30, %r11d + movq %r13, %rcx + addq %r14, %r10 + movq 16(%rdi), %r14 + movq -24(%rdi), %rax + movq 56(%rdi), %rdx + movq 40(%rdi), %r9 + addq %rsi, %r10 + addq %r15, %r10 + orq %r11, %r13 + andq %r11, %rcx + xorq %rax, %r14 + andq %rbx, %r13 + xorq %rdx, %r14 + orq %r13, %rcx + xorl %r9d, %r14d + movl %r10d, %r9d + roll %r14d + roll $5, %r9d + movq %r14, 40(%rdi) + movq 40(%rdi), %rsi + addq %rcx, %r9 + movq 24(%rdi), %r13 + addq %r12, %r9 + movq -16(%rdi), %r12 + movq 64(%rdi), %rax + movl %r10d, %r14d + addq %rsi, %r9 + movl %r8d, %esi + addq %r15, %r9 + movq 48(%rdi), %r15 + xorq %r12, %r13 + roll $30, %esi + xorq %rax, %r13 + xorq %rsi, %r10 + xorl %r15d, %r13d + movl %r9d, %r15d + xorq %r11, %r10 + roll $5, %r15d + roll %r13d + addq %r10, %r15 + movq %r13, 48(%rdi) + movq 48(%rdi), %r10 + addq %rbx, %r15 + movq 32(%rdi), %rbx + movq -8(%rdi), %r8 + movq 72(%rdi), %rdx + movq 56(%rdi), %rcx + roll $30, %r14d + addq %r10, %r15 + movl $3395469782, %r10d + movl %r9d, %r13d + xorq %r8, %rbx + addq %r10, %r15 + xorq %r14, %r9 + xorq %rdx, %rbx + xorq %rsi, %r9 + roll $30, %r13d + xorl %ecx, %ebx + movl %r15d, %ecx + roll %ebx + roll $5, %ecx + movq %rbx, 56(%rdi) + addq %r9, %rcx + movq 56(%rdi), %r12 + movq 40(%rdi), %r9 + movq (%rdi), %rax + addq %r11, %rcx + movq -48(%rdi), %r8 + movq 64(%rdi), %r11 + movl %r15d, %ebx + addq %r12, %rcx + xorq %r13, %r15 + roll $30, %ebx + xorq %rax, %r9 + addq %r10, %rcx + xorq %r14, %r15 + xorq %r8, %r9 + xorl %r11d, %r9d + movl %ecx, %r11d + roll %r9d + roll $5, %r11d + movq %r9, 64(%rdi) + addq %r15, %r11 + movq 64(%rdi), %rdx + movq 48(%rdi), %r15 + movq 8(%rdi), %r12 + addq %rsi, %r11 + movq -40(%rdi), %rax + movq 72(%rdi), %r8 + movl %ecx, %r9d + addq %rdx, %r11 + xorq %r12, %r15 + addq %r10, %r11 + xorq %rax, %r15 + xorl %r8d, %r15d + movl %r11d, %r8d + roll %r15d + roll $5, %r8d + xorq %rbx, %rcx + xorq %r13, %rcx + movq %r15, 72(%rdi) + movq 72(%rdi), %rsi + addq %rcx, %r8 + movq 56(%rdi), %r12 + movq 16(%rdi), %rcx + movq -32(%rdi), %rdx + addq %r14, %r8 + movq -48(%rdi), %r14 + addq %rsi, %r8 + roll $30, %r9d + movl %r11d, %r15d + xorq %rcx, %r12 + addq %r10, %r8 + xorq %r9, %r11 + xorq %rdx, %r12 + xorq %rbx, %r11 + roll $30, %r15d + xorl %r14d, %r12d + movl %r8d, %r14d + roll $5, %r14d + roll %r12d + addq %r11, %r14 + movq %r12, -48(%rdi) + movq -48(%rdi), %rax + addq %r13, %r14 + movq 64(%rdi), %r13 + movq 24(%rdi), %rsi + movq -24(%rdi), %rcx + movq -40(%rdi), %r11 + movl %r8d, %r12d + addq %rax, %r14 + xorq %r15, %r8 + roll $30, %r12d + xorq %rsi, %r13 + addq %r10, %r14 + xorq %r9, %r8 + xorq %rcx, %r13 + xorl %r11d, %r13d + movl %r14d, %r11d + roll $5, %r11d + roll %r13d + addq %r8, %r11 + movq %r13, -40(%rdi) + movq -40(%rdi), %rdx + addq %rbx, %r11 + movq 72(%rdi), %rbx + movq 32(%rdi), %rax + movq -16(%rdi), %rsi + movq -32(%rdi), %r8 + movl %r14d, %r13d + addq %rdx, %r11 + xorq %rax, %rbx + addq %r10, %r11 + xorq %rsi, %rbx + xorl %r8d, %ebx + xorq %r12, %r14 + movl %r11d, %r8d + xorq %r15, %r14 + roll %ebx + roll $5, %r8d + movq %rbx, -32(%rdi) + addq %r14, %r8 + movq -32(%rdi), %rcx + movq -48(%rdi), %r14 + movq 40(%rdi), %rdx + addq %r9, %r8 + movq -8(%rdi), %rax + movq -24(%rdi), %r9 + roll $30, %r13d + addq %rcx, %r8 + movl %r11d, %ebx + xorq %r13, %r11 + xorq %rdx, %r14 + addq %r10, %r8 + xorq %r12, %r11 + xorq %rax, %r14 + roll $30, %ebx + xorl %r9d, %r14d + movl %r8d, %r9d + roll $5, %r9d + roll %r14d + addq %r11, %r9 + movq %r14, -24(%rdi) + movq -24(%rdi), %rsi + addq %r15, %r9 + movq -40(%rdi), %r15 + movq 48(%rdi), %rcx + movq (%rdi), %rdx + movq -16(%rdi), %r11 + movl %r8d, %r14d + addq %rsi, %r9 + xorq %rbx, %r8 + xorq %rcx, %r15 + addq %r10, %r9 + xorq %r13, %r8 + xorq %rdx, %r15 + xorl %r11d, %r15d + movl %r9d, %r11d + roll %r15d + roll $5, %r11d + movq %r15, -16(%rdi) + addq %r8, %r11 + movq -16(%rdi), %rax + addq %r12, %r11 + movq -32(%rdi), %r12 + movq 56(%rdi), %rsi + movq 8(%rdi), %rcx + movq -8(%rdi), %r8 + movl %r9d, %r15d + addq %rax, %r11 + addq %r10, %r11 + roll $30, %r14d + xorq %rsi, %r12 + xorq %rcx, %r12 + xorq %r14, %r9 + roll $30, %r15d + xorl %r8d, %r12d + movl %r11d, %r8d + xorq %rbx, %r9 + roll $5, %r8d + roll %r12d + addq %r9, %r8 + movq %r12, -8(%rdi) + movq -8(%rdi), %rdx + addq %r13, %r8 + movq -24(%rdi), %r13 + movq 64(%rdi), %rax + movq 16(%rdi), %rsi + movq (%rdi), %rcx + movl %r11d, %r12d + addq %rdx, %r8 + xorq %r15, %r11 + roll $30, %r12d + xorq %rax, %r13 + addq %r10, %r8 + xorq %r14, %r11 + xorq %rsi, %r13 + xorl %ecx, %r13d + movl %r8d, %ecx + roll $5, %ecx + roll %r13d + addq %r11, %rcx + movq %r13, (%rdi) + movq (%rdi), %r9 + addq %rbx, %rcx + movq -16(%rdi), %rbx + movq 72(%rdi), %rdx + movq 24(%rdi), %rax + movq 8(%rdi), %rsi + movl %r8d, %r13d + addq %r9, %rcx + xorq %r12, %r8 + xorq %rdx, %rbx + addq %r10, %rcx + xorq %r15, %r8 + xorq %rax, %rbx + xorl %esi, %ebx + movl %ecx, %esi + roll $5, %esi + roll %ebx + addq %r8, %rsi + movq %rbx, 8(%rdi) + movq 8(%rdi), %r11 + addq %r14, %rsi + movq -8(%rdi), %r14 + movq -48(%rdi), %r9 + movq 32(%rdi), %rdx + movq 16(%rdi), %r8 + roll $30, %r13d + addq %r11, %rsi + movl %ecx, %ebx + xorq %r13, %rcx + xorq %r9, %r14 + addq %r10, %rsi + xorq %r12, %rcx + xorq %rdx, %r14 + roll $30, %ebx + xorl %r8d, %r14d + movl %esi, %r8d + roll $5, %r8d + roll %r14d + addq %rcx, %r8 + movq %r14, 16(%rdi) + movq 16(%rdi), %rax + addq %r15, %r8 + movq (%rdi), %r15 + movq -40(%rdi), %r11 + movq 40(%rdi), %r9 + movq 24(%rdi), %rcx + movl %esi, %r14d + addq %rax, %r8 + xorq %rbx, %rsi + roll $30, %r14d + xorq %r11, %r15 + addq %r10, %r8 + xorq %r13, %rsi + xorq %r9, %r15 + xorl %ecx, %r15d + movl %r8d, %ecx + roll %r15d + roll $5, %ecx + movq %r15, 24(%rdi) + addq %rsi, %rcx + movq 24(%rdi), %rdx + movq 8(%rdi), %r11 + movq -32(%rdi), %rax + addq %r12, %rcx + movq 48(%rdi), %r12 + movq 32(%rdi), %rsi + movl %r8d, %r15d + addq %rdx, %rcx + xorq %rax, %r11 + addq %r10, %rcx + xorq %r12, %r11 + xorl %esi, %r11d + movl %ecx, %esi + roll %r11d + movq %r11, 32(%rdi) + movl %ecx, %r11d + movq 32(%rdi), %r9 + roll $5, %r11d + xorq %r14, %r8 + movq 16(%rdi), %r12 + xorq %rbx, %r8 + movq -24(%rdi), %rdx + movq 56(%rdi), %rax + addq %r8, %r11 + movq 40(%rdi), %r8 + roll $30, %r15d + addq %r13, %r11 + xorq %r15, %rcx + addq %r9, %r11 + xorq %rdx, %r12 + xorq %r14, %rcx + addq %r10, %r11 + xorq %rax, %r12 + xorl %r8d, %r12d + movl %r11d, %r8d + roll $5, %r8d + roll %r12d + addq %rcx, %r8 + movq %r12, 40(%rdi) + movq 40(%rdi), %r13 + addq %rbx, %r8 + movq 24(%rdi), %rbx + movq -16(%rdi), %r9 + movq 64(%rdi), %rdx + movq 48(%rdi), %rcx + movl %r11d, %r12d + addq %r13, %r8 + movl %esi, %r13d + roll $30, %r12d + xorq %r9, %rbx + addq %r10, %r8 + roll $30, %r13d + xorq %rdx, %rbx + xorq %r13, %r11 + xorl %ecx, %ebx + movl %r8d, %ecx + xorq %r15, %r11 + roll %ebx + roll $5, %ecx + movq %rbx, 48(%rdi) + addq %r11, %rcx + movq 48(%rdi), %rax + movq 32(%rdi), %r11 + movq -8(%rdi), %rsi + addq %r14, %rcx + movq 72(%rdi), %r9 + movq 56(%rdi), %r14 + movl %r8d, %ebx + addq %rax, %rcx + xorq %rsi, %r11 + addq %r10, %rcx + xorq %r9, %r11 + xorl %r14d, %r11d + xorq %r12, %r8 + movl %ecx, %r14d + xorq %r13, %r8 + roll %r11d + roll $5, %r14d + movq %r11, 56(%rdi) + addq %r8, %r14 + movq 56(%rdi), %rdx + movq 40(%rdi), %r8 + movq (%rdi), %rax + addq %r15, %r14 + movq -48(%rdi), %r15 + movq 64(%rdi), %rsi + roll $30, %ebx + addq %rdx, %r14 + movl %ecx, %r11d + xorq %rbx, %rcx + xorq %rax, %r8 + addq %r10, %r14 + xorq %r12, %rcx + xorq %r15, %r8 + roll $30, %r11d + xorl %esi, %r8d + movl %r14d, %esi + roll %r8d + roll $5, %esi + movq %r8, 64(%rdi) + movq 64(%rdi), %r9 + addq %rcx, %rsi + movq 48(%rdi), %r15 + movq 8(%rdi), %rcx + addq %r13, %rsi + movq -40(%rdi), %rdx + movq 72(%rdi), %rax + movl %r14d, %r8d + addq %r9, %rsi + xorq %r11, %r14 + addq %r10, %rsi + xorq %rcx, %r15 + xorq %rbx, %r14 + xorq %rdx, %r15 + movl %esi, %r13d + xorl %eax, %r15d + roll $5, %r13d + roll %r15d + addq %r14, %r13 + movq %r15, 72(%rdi) + addq %r12, %r13 + movq 72(%rdi), %r12 + addq %r12, %r13 + addq %r10, %r13 + movq -88(%rdi), %r10 + roll $30, %r8d + addq %r13, %r10 + movq %r10, -88(%rdi) + movq -80(%rdi), %r9 + addq %rsi, %r9 + movq %r9, -80(%rdi) + movq -72(%rdi), %rcx + addq %r8, %rcx + movq %rcx, -72(%rdi) + movq -64(%rdi), %rdx + addq %r11, %rdx + movq %rdx, -64(%rdi) + movq -56(%rdi), %rax + addq %rbx, %rax + popq %rbx + popq %r12 + popq %r13 + popq %r14 + popq %r15 + movq %rax, -56(%rdi) + ret +.LFE7: + .size shaCompress, .-shaCompress + .align 16 +.globl SHA1_Update + .type SHA1_Update, @function +SHA1_Update: +.LFB5: + pushq %rbp +.LCFI5: + movq %rsp, %rbp +.LCFI6: + movq %r13, -24(%rbp) +.LCFI7: + movq %r14, -16(%rbp) +.LCFI8: + movl %edx, %r13d + movq %r15, -8(%rbp) +.LCFI9: + movq %rbx, -40(%rbp) +.LCFI10: + movq %rdi, %r15 + movq %r12, -32(%rbp) +.LCFI11: + subq $48, %rsp +.LCFI12: + testl %edx, %edx + movq %rsi, %r14 + je .L243 + movq 64(%rdi), %rdx + mov %r13d, %ecx + leaq (%rdx,%rcx), %rax + movq %rax, 64(%rdi) + movl %edx, %eax + andl $63, %eax + movl %eax, -44(%rbp) + jne .L256 +.L245: + cmpl $63, %r13d + jbe .L253 + leaq 160(%r15), %rbx + .align 16 +.L250: + movq %r14, %rsi + subl $64, %r13d + movq %rbx, %rdi + call shaCompress + addq $64, %r14 + cmpl $63, %r13d + ja .L250 +.L253: + testl %r13d, %r13d + je .L243 + mov %r13d, %edx + movq %r14, %rsi + movq %r15, %rdi + movq -40(%rbp), %rbx + movq -32(%rbp), %r12 + movq -24(%rbp), %r13 + movq -16(%rbp), %r14 + movq -8(%rbp), %r15 + leave + jmp memcpy@PLT + .align 16 +.L243: + movq -40(%rbp), %rbx + movq -32(%rbp), %r12 + movq -24(%rbp), %r13 + movq -16(%rbp), %r14 + movq -8(%rbp), %r15 + leave + ret +.L256: + movl $64, %ebx + mov %eax, %edi + subl %eax, %ebx + cmpl %ebx, %r13d + cmovb %r13d, %ebx + addq %r15, %rdi + mov %ebx, %r12d + subl %ebx, %r13d + movq %r12, %rdx + addq %r12, %r14 + call memcpy@PLT + addl -44(%rbp), %ebx + andl $63, %ebx + jne .L245 + leaq 160(%r15), %rdi + movq %r15, %rsi + call shaCompress + jmp .L245 +.LFE5: + .size SHA1_Update, .-SHA1_Update + .section .rodata + .align 32 + .type bulk_pad.0, @object + .size bulk_pad.0, 64 +bulk_pad.0: + .byte -128 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .byte 0 + .text + .align 16 +.globl SHA1_End + .type SHA1_End, @function +SHA1_End: +.LFB6: + pushq %rbp +.LCFI13: + movq %rsp, %rbp +.LCFI14: + movq %r12, -24(%rbp) +.LCFI15: + movq %r13, -16(%rbp) +.LCFI16: + movq %rsi, %r13 + movq %r14, -8(%rbp) +.LCFI17: + movq %rbx, -32(%rbp) +.LCFI18: + subq $32, %rsp +.LCFI19: + movq 64(%rdi), %rbx + movq %rdx, %r14 + movl $119, %edx + leaq bulk_pad.0(%rip), %rsi + movq %rdi, %r12 + movl %ebx, %r8d + salq $3, %rbx + andl $63, %r8d + subl %r8d, %edx + andl $63, %edx + incl %edx + call SHA1_Update@PLT + movq %rbx, %rdi + movq %r12, %rsi + shrq $32, %rdi +/APP + bswap %edi +/NO_APP + movl %edi, 56(%r12) + leaq 160(%r12), %rdi +/APP + bswap %ebx +/NO_APP + movl %ebx, 60(%r12) + call shaCompress + movl 72(%r12), %esi + movl 80(%r12), %ebx + movl 88(%r12), %ecx + movl 96(%r12), %edx + movl 104(%r12), %eax + movq 8(%rsp), %r12 +/APP + bswap %ebx + bswap %esi +/NO_APP + movl %ebx, 4(%r13) + movl %esi, (%r13) +/APP + bswap %ecx + bswap %edx +/NO_APP + movl %ecx, 8(%r13) + movl %edx, 12(%r13) +/APP + bswap %eax +/NO_APP + movq (%rsp), %rbx + movl %eax, 16(%r13) + movl $20, (%r14) + movq 16(%rsp), %r13 + movq 24(%rsp), %r14 + leave + ret +.LFE6: + .size SHA1_End, .-SHA1_End + .align 16 +.globl SHA1_NewContext + .type SHA1_NewContext, @function +SHA1_NewContext: +.LFB8: + movl $248, %edi + jmp PORT_Alloc@PLT +.LFE8: + .size SHA1_NewContext, .-SHA1_NewContext + .align 16 +.globl SHA1_DestroyContext + .type SHA1_DestroyContext, @function +SHA1_DestroyContext: +.LFB9: + pushq %rbp +.LCFI20: + movl $248, %edx + movq %rsp, %rbp +.LCFI21: + movq %rbx, -16(%rbp) +.LCFI22: + movq %r12, -8(%rbp) +.LCFI23: + movl %esi, %ebx + subq $16, %rsp +.LCFI24: + xorl %esi, %esi + movq %rdi, %r12 + call memset@PLT + testl %ebx, %ebx + jne .L268 + movq (%rsp), %rbx + movq 8(%rsp), %r12 + leave + ret + .align 16 +.L268: + movq %r12, %rdi + movq (%rsp), %rbx + movq 8(%rsp), %r12 + leave + jmp PORT_Free@PLT +.LFE9: + .size SHA1_DestroyContext, .-SHA1_DestroyContext + .align 16 +.globl SHA1_HashBuf + .type SHA1_HashBuf, @function +SHA1_HashBuf: +.LFB10: + pushq %rbp +.LCFI25: + movq %rsp, %rbp +.LCFI26: + movq %rbx, -32(%rbp) +.LCFI27: + leaq -288(%rbp), %rbx + movq %r12, -24(%rbp) +.LCFI28: + movq %r13, -16(%rbp) +.LCFI29: + movq %r14, -8(%rbp) +.LCFI30: + movq %rsi, %r13 + subq $304, %rsp +.LCFI31: + movq %rdi, %r14 + movl %edx, %r12d + movq %rbx, %rdi + call SHA1_Begin@PLT + movl %r12d, %edx + movq %r13, %rsi + movq %rbx, %rdi + call SHA1_Update@PLT + leaq -292(%rbp), %rdx + movq %r14, %rsi + movq %rbx, %rdi + movl $20, %ecx + call SHA1_End@PLT + movq -32(%rbp), %rbx + movq -24(%rbp), %r12 + xorl %eax, %eax + movq -16(%rbp), %r13 + movq -8(%rbp), %r14 + leave + ret +.LFE10: + .size SHA1_HashBuf, .-SHA1_HashBuf + .align 16 +.globl SHA1_Hash + .type SHA1_Hash, @function +SHA1_Hash: +.LFB11: + pushq %rbp +.LCFI32: + movq %rsp, %rbp +.LCFI33: + movq %rbx, -16(%rbp) +.LCFI34: + movq %r12, -8(%rbp) +.LCFI35: + movq %rsi, %rbx + subq $16, %rsp +.LCFI36: + movq %rdi, %r12 + movq %rsi, %rdi + call strlen@PLT + movq %rbx, %rsi + movq %r12, %rdi + movq (%rsp), %rbx + movq 8(%rsp), %r12 + leave + movl %eax, %edx + jmp SHA1_HashBuf@PLT +.LFE11: + .size SHA1_Hash, .-SHA1_Hash + .align 16 +.globl SHA1_FlattenSize + .type SHA1_FlattenSize, @function +SHA1_FlattenSize: +.LFB12: + movl $248, %eax + ret +.LFE12: + .size SHA1_FlattenSize, .-SHA1_FlattenSize + .align 16 +.globl SHA1_Flatten + .type SHA1_Flatten, @function +SHA1_Flatten: +.LFB13: + pushq %rbp +.LCFI37: + movq %rsi, %rax + movl $248, %edx + movq %rdi, %rsi + movq %rax, %rdi + movq %rsp, %rbp +.LCFI38: + call memcpy@PLT + leave + xorl %eax, %eax + ret +.LFE13: + .size SHA1_Flatten, .-SHA1_Flatten + .align 16 +.globl SHA1_Resurrect + .type SHA1_Resurrect, @function +SHA1_Resurrect: +.LFB14: + pushq %rbp +.LCFI39: + movq %rsp, %rbp +.LCFI40: + movq %rbx, -16(%rbp) +.LCFI41: + movq %r12, -8(%rbp) +.LCFI42: + subq $16, %rsp +.LCFI43: + movq %rdi, %r12 + call SHA1_NewContext@PLT + movq %rax, %rbx + xorl %eax, %eax + testq %rbx, %rbx + je .L273 + movl $248, %edx + movq %r12, %rsi + movq %rbx, %rdi + call memcpy@PLT + movq %rbx, %rax +.L273: + movq (%rsp), %rbx + movq 8(%rsp), %r12 + leave + ret +.LFE14: + .size SHA1_Resurrect, .-SHA1_Resurrect + .align 16 +.globl SHA1_Clone + .type SHA1_Clone, @function +SHA1_Clone: +.LFB15: + movl $248, %edx + jmp memcpy@PLT +.LFE15: + .size SHA1_Clone, .-SHA1_Clone + .align 16 +.globl SHA1_TraceState + .type SHA1_TraceState, @function +SHA1_TraceState: +.LFB16: + movl $-5992, %edi + jmp PORT_SetError@PLT +.LFE16: + .size SHA1_TraceState, .-SHA1_TraceState diff --git a/security/nss/lib/freebl/sha512.c b/security/nss/lib/freebl/sha512.c index ada93e62f..672aa9a0f 100644 --- a/security/nss/lib/freebl/sha512.c +++ b/security/nss/lib/freebl/sha512.c @@ -515,6 +515,11 @@ SHA256_Resurrect(unsigned char *space, void *arg) return ctx; } +void SHA256_Clone(SHA256Context *dest, SHA256Context *src) +{ + memcpy(dest, src, sizeof *dest); +} + /* ======= SHA512 and SHA384 common constants and defines ================= */ @@ -1168,6 +1173,11 @@ SHA512_Resurrect(unsigned char *space, void *arg) return ctx; } +void SHA512_Clone(SHA512Context *dest, SHA512Context *src) +{ + memcpy(dest, src, sizeof *dest); +} + /* ======================================================================= */ /* SHA384 uses a SHA512Context as the real context. ** The only differences between SHA384 an SHA512 are: @@ -1265,6 +1275,11 @@ SHA384_Resurrect(unsigned char *space, void *arg) return SHA512_Resurrect(space, arg); } +void SHA384_Clone(SHA384Context *dest, SHA384Context *src) +{ + memcpy(dest, src, sizeof *dest); +} + /* ======================================================================= */ #ifdef SELFTEST #include <stdio.h> diff --git a/security/nss/lib/freebl/sha_fast.c b/security/nss/lib/freebl/sha_fast.c index 7bdb0824c..b59e3ce39 100644 --- a/security/nss/lib/freebl/sha_fast.c +++ b/security/nss/lib/freebl/sha_fast.c @@ -43,56 +43,26 @@ #include "ssltrace.h" #endif -#if defined(IS_LITTLE_ENDIAN) && defined(_MSC_VER) && defined(_X86_) -#undef SHA_HTONL -#ifndef FORCEINLINE -#if (MSC_VER >= 1200) -#define FORCEINLINE __forceinline -#else -#define FORCEINLINE __inline -#endif -#endif -#define FASTCALL __fastcall - -static FORCEINLINE PRUint32 FASTCALL -swap4b(PRUint32 dwd) -{ - __asm { - mov eax,dwd - bswap eax - } -} - -#define SHA_HTONL(x) swap4b(x) -#endif - -static void shaCompress(SHA1Context *ctx); +static void shaCompress(volatile SHA_HW_t *X, const PRUint32 * datain); #define W u.w #define B u.b -#if defined(_MSC_VER) && defined(_X86_) -#pragma intrinsic (_lrotr, _lrotl) -#define SHA_ROTL(x,n) _lrotl(x,n) -#else -#define SHA_ROTL(X,n) (((X) << (n)) | ((X) >> (32-(n)))) -#endif + #define SHA_F1(X,Y,Z) ((((Y)^(Z))&(X))^(Z)) #define SHA_F2(X,Y,Z) ((X)^(Y)^(Z)) #define SHA_F3(X,Y,Z) (((X)&(Y))|((Z)&((X)|(Y)))) #define SHA_F4(X,Y,Z) ((X)^(Y)^(Z)) -#define SHA_MIX(t) ctx->W[t] = \ - (A = ctx->W[t-3] ^ ctx->W[t-8] ^ ctx->W[t-14] ^ ctx->W[t-16], SHA_ROTL(A, 1)) +#define SHA_MIX(n,a,b,c) XW(n) = SHA_ROTL(XW(a)^XW(b)^XW(c)^XW(n), 1) /* - * SHA: Zeroize and initialize context + * SHA: initialize context */ void SHA1_Begin(SHA1Context *ctx) { - memset(ctx, 0, sizeof(SHA1Context)); - + ctx->size = 0; /* * Initialize H with constants from FIPS180-1. */ @@ -103,6 +73,43 @@ SHA1_Begin(SHA1Context *ctx) ctx->H[4] = 0xc3d2e1f0L; } +/* Explanation of H array and index values: + * The context's H array is actually the concatenation of two arrays + * defined by SHA1, the H array of state variables (5 elements), + * and the W array of intermediate values, of which there are 16 elements. + * The W array starts at H[5], that is W[0] is H[5]. + * Although these values are defined as 32-bit values, we use 64-bit + * variables to hold them because the AMD64 stores 64 bit values in + * memory MUCH faster than it stores any smaller values. + * + * Rather than passing the context structure to shaCompress, we pass + * this combined array of H and W values. We do not pass the address + * of the first element of this array, but rather pass the address of an + * element in the middle of the array, element X. Presently X[0] is H[11]. + * So we pass the address of H[11] as the address of array X to shaCompress. + * Then shaCompress accesses the members of the array using positive AND + * negative indexes. + * + * Pictorially: (each element is 8 bytes) + * H | H0 H1 H2 H3 H4 W0 W1 W2 W3 W4 W5 W6 W7 W8 W9 Wa Wb Wc Wd We Wf | + * X |-11-10 -9 -8 -7 -6 -5 -4 -3 -2 -1 X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 | + * + * The byte offset from X[0] to any member of H and W is always + * representable in a signed 8-bit value, which will be encoded + * as a single byte offset in the X86-64 instruction set. + * If we didn't pass the address of H[11], and instead passed the + * address of H[0], the offsets to elements H[16] and above would be + * greater than 127, not representable in a signed 8-bit value, and the + * x86-64 instruction set would encode every such offset as a 32-bit + * signed number in each instruction that accessed element H[16] or + * higher. This results in much bigger and slower code. + */ +#if !defined(SHA_PUT_W_IN_STACK) +#define H2X 11 /* X[0] is H[11], and H[0] is X[-11] */ +#define W2X 6 /* X[0] is W[6], and W[0] is X[-6] */ +#else +#define H2X 0 +#endif /* * SHA: Add data to context. @@ -110,36 +117,48 @@ SHA1_Begin(SHA1Context *ctx) void SHA1_Update(SHA1Context *ctx, const unsigned char *dataIn, unsigned int len) { - register unsigned int lenB = ctx->sizeLo & 63; + register unsigned int lenB; register unsigned int togo; if (!len) return; /* accumulate the byte count. */ - ctx->sizeLo += len; - ctx->sizeHi += (ctx->sizeLo < len); + lenB = (unsigned int)(ctx->size) & 63U; + + ctx->size += len; /* * Read the data into W and process blocks as they get full */ if (lenB > 0) { - togo = 64 - lenB; + togo = 64U - lenB; if (len < togo) togo = len; memcpy(ctx->B + lenB, dataIn, togo); len -= togo; dataIn += togo; - lenB = (lenB + togo) & 63; + lenB = (lenB + togo) & 63U; if (!lenB) { - shaCompress(ctx); + shaCompress(&ctx->H[H2X], ctx->W); } } - while (len >= 64) { - memcpy(ctx->B, dataIn, 64); - dataIn += 64; - len -= 64; - shaCompress(ctx); +#if !defined(SHA_ALLOW_UNALIGNED_ACCESS) + if ((ptrdiff_t)dataIn % sizeof(PRUint32)) { + while (len >= 64U) { + memcpy(ctx->B, dataIn, 64); + len -= 64U; + shaCompress(&ctx->H[H2X], ctx->W); + dataIn += 64U; + } + } else +#endif + { + while (len >= 64U) { + len -= 64U; + shaCompress(&ctx->H[H2X], (PRUint32 *)dataIn); + dataIn += 64U; + } } if (len) { memcpy(ctx->B, dataIn, len); @@ -154,194 +173,221 @@ void SHA1_End(SHA1Context *ctx, unsigned char *hashout, unsigned int *pDigestLen, unsigned int maxDigestLen) { - register PRUint32 sizeHi, sizeLo, lenB; + register PRUint64 size; + register PRUint32 lenB; + static const unsigned char bulk_pad[64] = { 0x80,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; -#define A lenB +#define tmp lenB PORT_Assert (maxDigestLen >= SHA1_LENGTH); /* * Pad with a binary 1 (e.g. 0x80), then zeroes, then length in bits */ - sizeHi = ctx->sizeHi; - sizeLo = ctx->sizeLo; - lenB = sizeLo & 63; - SHA1_Update(ctx, bulk_pad, (((55+64) - lenB) & 63) + 1); - PORT_Assert((ctx->sizeLo & 63) == 56); - - /* Convert size{Hi,Lo} from bytes to bits. */ - sizeHi = (sizeHi << 3) | (sizeLo >> 29); - sizeLo <<= 3; + size = ctx->size; - ctx->W[14] = SHA_HTONL(sizeHi); - ctx->W[15] = SHA_HTONL(sizeLo); - shaCompress(ctx); + lenB = (PRUint32)size & 63; + SHA1_Update(ctx, bulk_pad, (((55+64) - lenB) & 63) + 1); + PORT_Assert(((PRUint32)ctx->size & 63) == 56); + /* Convert size from bytes to bits. */ + size <<= 3; + ctx->W[14] = SHA_HTONL((PRUint32)(size >> 32)); + ctx->W[15] = SHA_HTONL((PRUint32)size); + shaCompress(&ctx->H[H2X], ctx->W); /* * Output hash */ -#if defined(IS_LITTLE_ENDIAN) - SHA_BYTESWAP(ctx->H[0]); - SHA_BYTESWAP(ctx->H[1]); - SHA_BYTESWAP(ctx->H[2]); - SHA_BYTESWAP(ctx->H[3]); - SHA_BYTESWAP(ctx->H[4]); -#endif - memcpy(hashout, ctx->H, SHA1_LENGTH); + SHA_STORE_RESULT; *pDigestLen = SHA1_LENGTH; - /* - * Re-initialize the context (also zeroizes contents) - */ - SHA1_Begin(ctx); } -#undef A #undef B +#undef tmp /* * SHA: Compression function, unrolled. + * + * Some operations in shaCompress are done as 5 groups of 16 operations. + * Others are done as 4 groups of 20 operations. + * The code below shows that structure. + * + * The functions that compute the new values of the 5 state variables + * A-E are done in 4 groups of 20 operations (or you may also think + * of them as being done in 16 groups of 5 operations). They are + * done by the SHA_RNDx macros below, in the right column. + * + * The functions that set the 16 values of the W array are done in + * 5 groups of 16 operations. The first group is done by the + * LOAD macros below, the latter 4 groups are done by SHA_MIX below, + * in the left column. + * + * gcc's optimizer observes that each member of the W array is assigned + * a value 5 times in this code. It reduces the number of store + * operations done to the W array in the context (that is, in the X array) + * by creating a W array on the stack, and storing the W values there for + * the first 4 groups of operations on W, and storing the values in the + * context's W array only in the fifth group. This is undesirable. + * It is MUCH bigger code than simply using the context's W array, because + * all the offsets to the W array in the stack are 32-bit signed offsets, + * and it is no faster than storing the values in the context's W array. + * + * The original code for sha_fast.c prevented this creation of a separate + * W array in the stack by creating a W array of 80 members, each of + * whose elements is assigned only once. It also separated the computations + * of the W array values and the computations of the values for the 5 + * state variables into two separate passes, W's, then A-E's so that the + * second pass could be done all in registers (except for accessing the W + * array) on machines with fewer registers. The method is suboptimal + * for machines with enough registers to do it all in one pass, and it + * necessitates using many instructions with 32-bit offsets. + * + * This code eliminates the separate W array on the stack by a completely + * different means: by declaring the X array volatile. This prevents + * the optimizer from trying to reduce the use of the X array by the + * creation of a MORE expensive W array on the stack. The result is + * that all instructions use signed 8-bit offsets and not 32-bit offsets. + * + * The combination of this code and the -O3 optimizer flag on GCC 3.4.3 + * results in code that is 3 times faster than the previous NSS sha_fast + * code on AMD64. */ static void -shaCompress(SHA1Context *ctx) +shaCompress(volatile SHA_HW_t *X, const PRUint32 *inbuf) { - register PRUint32 A, B, C, D, E; - -#if defined(IS_LITTLE_ENDIAN) - SHA_BYTESWAP(ctx->W[0]); - SHA_BYTESWAP(ctx->W[1]); - SHA_BYTESWAP(ctx->W[2]); - SHA_BYTESWAP(ctx->W[3]); - SHA_BYTESWAP(ctx->W[4]); - SHA_BYTESWAP(ctx->W[5]); - SHA_BYTESWAP(ctx->W[6]); - SHA_BYTESWAP(ctx->W[7]); - SHA_BYTESWAP(ctx->W[8]); - SHA_BYTESWAP(ctx->W[9]); - SHA_BYTESWAP(ctx->W[10]); - SHA_BYTESWAP(ctx->W[11]); - SHA_BYTESWAP(ctx->W[12]); - SHA_BYTESWAP(ctx->W[13]); - SHA_BYTESWAP(ctx->W[14]); - SHA_BYTESWAP(ctx->W[15]); + register SHA_HW_t A, B, C, D, E; + +#if defined(SHA_NEED_TMP_VARIABLE) + register PRUint32 tmp; #endif - /* - * This can be moved into the main code block below, but doing - * so can cause some compilers to run out of registers and resort - * to storing intermediates in RAM. - */ +#if !defined(SHA_PUT_W_IN_STACK) +#define XH(n) X[n-H2X] +#define XW(n) X[n-W2X] +#else + SHA_HW_t w_0, w_1, w_2, w_3, w_4, w_5, w_6, w_7, + w_8, w_9, w_10, w_11, w_12, w_13, w_14, w_15; +#define XW(n) w_ ## n +#define XH(n) X[n] +#endif - SHA_MIX(16); SHA_MIX(17); SHA_MIX(18); SHA_MIX(19); - SHA_MIX(20); SHA_MIX(21); SHA_MIX(22); SHA_MIX(23); SHA_MIX(24); - SHA_MIX(25); SHA_MIX(26); SHA_MIX(27); SHA_MIX(28); SHA_MIX(29); - SHA_MIX(30); SHA_MIX(31); SHA_MIX(32); SHA_MIX(33); SHA_MIX(34); - SHA_MIX(35); SHA_MIX(36); SHA_MIX(37); SHA_MIX(38); SHA_MIX(39); - SHA_MIX(40); SHA_MIX(41); SHA_MIX(42); SHA_MIX(43); SHA_MIX(44); - SHA_MIX(45); SHA_MIX(46); SHA_MIX(47); SHA_MIX(48); SHA_MIX(49); - SHA_MIX(50); SHA_MIX(51); SHA_MIX(52); SHA_MIX(53); SHA_MIX(54); - SHA_MIX(55); SHA_MIX(56); SHA_MIX(57); SHA_MIX(58); SHA_MIX(59); - SHA_MIX(60); SHA_MIX(61); SHA_MIX(62); SHA_MIX(63); SHA_MIX(64); - SHA_MIX(65); SHA_MIX(66); SHA_MIX(67); SHA_MIX(68); SHA_MIX(69); - SHA_MIX(70); SHA_MIX(71); SHA_MIX(72); SHA_MIX(73); SHA_MIX(74); - SHA_MIX(75); SHA_MIX(76); SHA_MIX(77); SHA_MIX(78); SHA_MIX(79); - - A = ctx->H[0]; - B = ctx->H[1]; - C = ctx->H[2]; - D = ctx->H[3]; - E = ctx->H[4]; - - E = SHA_ROTL(A,5)+SHA_F1(B,C,D)+E+ctx->W[ 0]+0x5a827999L; B=SHA_ROTL(B,30); - D = SHA_ROTL(E,5)+SHA_F1(A,B,C)+D+ctx->W[ 1]+0x5a827999L; A=SHA_ROTL(A,30); - C = SHA_ROTL(D,5)+SHA_F1(E,A,B)+C+ctx->W[ 2]+0x5a827999L; E=SHA_ROTL(E,30); - B = SHA_ROTL(C,5)+SHA_F1(D,E,A)+B+ctx->W[ 3]+0x5a827999L; D=SHA_ROTL(D,30); - A = SHA_ROTL(B,5)+SHA_F1(C,D,E)+A+ctx->W[ 4]+0x5a827999L; C=SHA_ROTL(C,30); - E = SHA_ROTL(A,5)+SHA_F1(B,C,D)+E+ctx->W[ 5]+0x5a827999L; B=SHA_ROTL(B,30); - D = SHA_ROTL(E,5)+SHA_F1(A,B,C)+D+ctx->W[ 6]+0x5a827999L; A=SHA_ROTL(A,30); - C = SHA_ROTL(D,5)+SHA_F1(E,A,B)+C+ctx->W[ 7]+0x5a827999L; E=SHA_ROTL(E,30); - B = SHA_ROTL(C,5)+SHA_F1(D,E,A)+B+ctx->W[ 8]+0x5a827999L; D=SHA_ROTL(D,30); - A = SHA_ROTL(B,5)+SHA_F1(C,D,E)+A+ctx->W[ 9]+0x5a827999L; C=SHA_ROTL(C,30); - E = SHA_ROTL(A,5)+SHA_F1(B,C,D)+E+ctx->W[10]+0x5a827999L; B=SHA_ROTL(B,30); - D = SHA_ROTL(E,5)+SHA_F1(A,B,C)+D+ctx->W[11]+0x5a827999L; A=SHA_ROTL(A,30); - C = SHA_ROTL(D,5)+SHA_F1(E,A,B)+C+ctx->W[12]+0x5a827999L; E=SHA_ROTL(E,30); - B = SHA_ROTL(C,5)+SHA_F1(D,E,A)+B+ctx->W[13]+0x5a827999L; D=SHA_ROTL(D,30); - A = SHA_ROTL(B,5)+SHA_F1(C,D,E)+A+ctx->W[14]+0x5a827999L; C=SHA_ROTL(C,30); - E = SHA_ROTL(A,5)+SHA_F1(B,C,D)+E+ctx->W[15]+0x5a827999L; B=SHA_ROTL(B,30); - D = SHA_ROTL(E,5)+SHA_F1(A,B,C)+D+ctx->W[16]+0x5a827999L; A=SHA_ROTL(A,30); - C = SHA_ROTL(D,5)+SHA_F1(E,A,B)+C+ctx->W[17]+0x5a827999L; E=SHA_ROTL(E,30); - B = SHA_ROTL(C,5)+SHA_F1(D,E,A)+B+ctx->W[18]+0x5a827999L; D=SHA_ROTL(D,30); - A = SHA_ROTL(B,5)+SHA_F1(C,D,E)+A+ctx->W[19]+0x5a827999L; C=SHA_ROTL(C,30); - - E = SHA_ROTL(A,5)+SHA_F2(B,C,D)+E+ctx->W[20]+0x6ed9eba1L; B=SHA_ROTL(B,30); - D = SHA_ROTL(E,5)+SHA_F2(A,B,C)+D+ctx->W[21]+0x6ed9eba1L; A=SHA_ROTL(A,30); - C = SHA_ROTL(D,5)+SHA_F2(E,A,B)+C+ctx->W[22]+0x6ed9eba1L; E=SHA_ROTL(E,30); - B = SHA_ROTL(C,5)+SHA_F2(D,E,A)+B+ctx->W[23]+0x6ed9eba1L; D=SHA_ROTL(D,30); - A = SHA_ROTL(B,5)+SHA_F2(C,D,E)+A+ctx->W[24]+0x6ed9eba1L; C=SHA_ROTL(C,30); - E = SHA_ROTL(A,5)+SHA_F2(B,C,D)+E+ctx->W[25]+0x6ed9eba1L; B=SHA_ROTL(B,30); - D = SHA_ROTL(E,5)+SHA_F2(A,B,C)+D+ctx->W[26]+0x6ed9eba1L; A=SHA_ROTL(A,30); - C = SHA_ROTL(D,5)+SHA_F2(E,A,B)+C+ctx->W[27]+0x6ed9eba1L; E=SHA_ROTL(E,30); - B = SHA_ROTL(C,5)+SHA_F2(D,E,A)+B+ctx->W[28]+0x6ed9eba1L; D=SHA_ROTL(D,30); - A = SHA_ROTL(B,5)+SHA_F2(C,D,E)+A+ctx->W[29]+0x6ed9eba1L; C=SHA_ROTL(C,30); - E = SHA_ROTL(A,5)+SHA_F2(B,C,D)+E+ctx->W[30]+0x6ed9eba1L; B=SHA_ROTL(B,30); - D = SHA_ROTL(E,5)+SHA_F2(A,B,C)+D+ctx->W[31]+0x6ed9eba1L; A=SHA_ROTL(A,30); - C = SHA_ROTL(D,5)+SHA_F2(E,A,B)+C+ctx->W[32]+0x6ed9eba1L; E=SHA_ROTL(E,30); - B = SHA_ROTL(C,5)+SHA_F2(D,E,A)+B+ctx->W[33]+0x6ed9eba1L; D=SHA_ROTL(D,30); - A = SHA_ROTL(B,5)+SHA_F2(C,D,E)+A+ctx->W[34]+0x6ed9eba1L; C=SHA_ROTL(C,30); - E = SHA_ROTL(A,5)+SHA_F2(B,C,D)+E+ctx->W[35]+0x6ed9eba1L; B=SHA_ROTL(B,30); - D = SHA_ROTL(E,5)+SHA_F2(A,B,C)+D+ctx->W[36]+0x6ed9eba1L; A=SHA_ROTL(A,30); - C = SHA_ROTL(D,5)+SHA_F2(E,A,B)+C+ctx->W[37]+0x6ed9eba1L; E=SHA_ROTL(E,30); - B = SHA_ROTL(C,5)+SHA_F2(D,E,A)+B+ctx->W[38]+0x6ed9eba1L; D=SHA_ROTL(D,30); - A = SHA_ROTL(B,5)+SHA_F2(C,D,E)+A+ctx->W[39]+0x6ed9eba1L; C=SHA_ROTL(C,30); - - E = SHA_ROTL(A,5)+SHA_F3(B,C,D)+E+ctx->W[40]+0x8f1bbcdcL; B=SHA_ROTL(B,30); - D = SHA_ROTL(E,5)+SHA_F3(A,B,C)+D+ctx->W[41]+0x8f1bbcdcL; A=SHA_ROTL(A,30); - C = SHA_ROTL(D,5)+SHA_F3(E,A,B)+C+ctx->W[42]+0x8f1bbcdcL; E=SHA_ROTL(E,30); - B = SHA_ROTL(C,5)+SHA_F3(D,E,A)+B+ctx->W[43]+0x8f1bbcdcL; D=SHA_ROTL(D,30); - A = SHA_ROTL(B,5)+SHA_F3(C,D,E)+A+ctx->W[44]+0x8f1bbcdcL; C=SHA_ROTL(C,30); - E = SHA_ROTL(A,5)+SHA_F3(B,C,D)+E+ctx->W[45]+0x8f1bbcdcL; B=SHA_ROTL(B,30); - D = SHA_ROTL(E,5)+SHA_F3(A,B,C)+D+ctx->W[46]+0x8f1bbcdcL; A=SHA_ROTL(A,30); - C = SHA_ROTL(D,5)+SHA_F3(E,A,B)+C+ctx->W[47]+0x8f1bbcdcL; E=SHA_ROTL(E,30); - B = SHA_ROTL(C,5)+SHA_F3(D,E,A)+B+ctx->W[48]+0x8f1bbcdcL; D=SHA_ROTL(D,30); - A = SHA_ROTL(B,5)+SHA_F3(C,D,E)+A+ctx->W[49]+0x8f1bbcdcL; C=SHA_ROTL(C,30); - E = SHA_ROTL(A,5)+SHA_F3(B,C,D)+E+ctx->W[50]+0x8f1bbcdcL; B=SHA_ROTL(B,30); - D = SHA_ROTL(E,5)+SHA_F3(A,B,C)+D+ctx->W[51]+0x8f1bbcdcL; A=SHA_ROTL(A,30); - C = SHA_ROTL(D,5)+SHA_F3(E,A,B)+C+ctx->W[52]+0x8f1bbcdcL; E=SHA_ROTL(E,30); - B = SHA_ROTL(C,5)+SHA_F3(D,E,A)+B+ctx->W[53]+0x8f1bbcdcL; D=SHA_ROTL(D,30); - A = SHA_ROTL(B,5)+SHA_F3(C,D,E)+A+ctx->W[54]+0x8f1bbcdcL; C=SHA_ROTL(C,30); - E = SHA_ROTL(A,5)+SHA_F3(B,C,D)+E+ctx->W[55]+0x8f1bbcdcL; B=SHA_ROTL(B,30); - D = SHA_ROTL(E,5)+SHA_F3(A,B,C)+D+ctx->W[56]+0x8f1bbcdcL; A=SHA_ROTL(A,30); - C = SHA_ROTL(D,5)+SHA_F3(E,A,B)+C+ctx->W[57]+0x8f1bbcdcL; E=SHA_ROTL(E,30); - B = SHA_ROTL(C,5)+SHA_F3(D,E,A)+B+ctx->W[58]+0x8f1bbcdcL; D=SHA_ROTL(D,30); - A = SHA_ROTL(B,5)+SHA_F3(C,D,E)+A+ctx->W[59]+0x8f1bbcdcL; C=SHA_ROTL(C,30); - - E = SHA_ROTL(A,5)+SHA_F4(B,C,D)+E+ctx->W[60]+0xca62c1d6L; B=SHA_ROTL(B,30); - D = SHA_ROTL(E,5)+SHA_F4(A,B,C)+D+ctx->W[61]+0xca62c1d6L; A=SHA_ROTL(A,30); - C = SHA_ROTL(D,5)+SHA_F4(E,A,B)+C+ctx->W[62]+0xca62c1d6L; E=SHA_ROTL(E,30); - B = SHA_ROTL(C,5)+SHA_F4(D,E,A)+B+ctx->W[63]+0xca62c1d6L; D=SHA_ROTL(D,30); - A = SHA_ROTL(B,5)+SHA_F4(C,D,E)+A+ctx->W[64]+0xca62c1d6L; C=SHA_ROTL(C,30); - E = SHA_ROTL(A,5)+SHA_F4(B,C,D)+E+ctx->W[65]+0xca62c1d6L; B=SHA_ROTL(B,30); - D = SHA_ROTL(E,5)+SHA_F4(A,B,C)+D+ctx->W[66]+0xca62c1d6L; A=SHA_ROTL(A,30); - C = SHA_ROTL(D,5)+SHA_F4(E,A,B)+C+ctx->W[67]+0xca62c1d6L; E=SHA_ROTL(E,30); - B = SHA_ROTL(C,5)+SHA_F4(D,E,A)+B+ctx->W[68]+0xca62c1d6L; D=SHA_ROTL(D,30); - A = SHA_ROTL(B,5)+SHA_F4(C,D,E)+A+ctx->W[69]+0xca62c1d6L; C=SHA_ROTL(C,30); - E = SHA_ROTL(A,5)+SHA_F4(B,C,D)+E+ctx->W[70]+0xca62c1d6L; B=SHA_ROTL(B,30); - D = SHA_ROTL(E,5)+SHA_F4(A,B,C)+D+ctx->W[71]+0xca62c1d6L; A=SHA_ROTL(A,30); - C = SHA_ROTL(D,5)+SHA_F4(E,A,B)+C+ctx->W[72]+0xca62c1d6L; E=SHA_ROTL(E,30); - B = SHA_ROTL(C,5)+SHA_F4(D,E,A)+B+ctx->W[73]+0xca62c1d6L; D=SHA_ROTL(D,30); - A = SHA_ROTL(B,5)+SHA_F4(C,D,E)+A+ctx->W[74]+0xca62c1d6L; C=SHA_ROTL(C,30); - E = SHA_ROTL(A,5)+SHA_F4(B,C,D)+E+ctx->W[75]+0xca62c1d6L; B=SHA_ROTL(B,30); - D = SHA_ROTL(E,5)+SHA_F4(A,B,C)+D+ctx->W[76]+0xca62c1d6L; A=SHA_ROTL(A,30); - C = SHA_ROTL(D,5)+SHA_F4(E,A,B)+C+ctx->W[77]+0xca62c1d6L; E=SHA_ROTL(E,30); - B = SHA_ROTL(C,5)+SHA_F4(D,E,A)+B+ctx->W[78]+0xca62c1d6L; D=SHA_ROTL(D,30); - A = SHA_ROTL(B,5)+SHA_F4(C,D,E)+A+ctx->W[79]+0xca62c1d6L; C=SHA_ROTL(C,30); - - ctx->H[0] += A; - ctx->H[1] += B; - ctx->H[2] += C; - ctx->H[3] += D; - ctx->H[4] += E; +#define K0 0x5a827999L +#define K1 0x6ed9eba1L +#define K2 0x8f1bbcdcL +#define K3 0xca62c1d6L + +#define SHA_RND1(a,b,c,d,e,n) \ + a = SHA_ROTL(b,5)+SHA_F1(c,d,e)+a+XW(n)+K0; c=SHA_ROTL(c,30) +#define SHA_RND2(a,b,c,d,e,n) \ + a = SHA_ROTL(b,5)+SHA_F2(c,d,e)+a+XW(n)+K1; c=SHA_ROTL(c,30) +#define SHA_RND3(a,b,c,d,e,n) \ + a = SHA_ROTL(b,5)+SHA_F3(c,d,e)+a+XW(n)+K2; c=SHA_ROTL(c,30) +#define SHA_RND4(a,b,c,d,e,n) \ + a = SHA_ROTL(b,5)+SHA_F4(c,d,e)+a+XW(n)+K3; c=SHA_ROTL(c,30) + +#define LOAD(n) XW(n) = SHA_HTONL(inbuf[n]) + + A = XH(0); + B = XH(1); + C = XH(2); + D = XH(3); + E = XH(4); + + LOAD(0); SHA_RND1(E,A,B,C,D, 0); + LOAD(1); SHA_RND1(D,E,A,B,C, 1); + LOAD(2); SHA_RND1(C,D,E,A,B, 2); + LOAD(3); SHA_RND1(B,C,D,E,A, 3); + LOAD(4); SHA_RND1(A,B,C,D,E, 4); + LOAD(5); SHA_RND1(E,A,B,C,D, 5); + LOAD(6); SHA_RND1(D,E,A,B,C, 6); + LOAD(7); SHA_RND1(C,D,E,A,B, 7); + LOAD(8); SHA_RND1(B,C,D,E,A, 8); + LOAD(9); SHA_RND1(A,B,C,D,E, 9); + LOAD(10); SHA_RND1(E,A,B,C,D,10); + LOAD(11); SHA_RND1(D,E,A,B,C,11); + LOAD(12); SHA_RND1(C,D,E,A,B,12); + LOAD(13); SHA_RND1(B,C,D,E,A,13); + LOAD(14); SHA_RND1(A,B,C,D,E,14); + LOAD(15); SHA_RND1(E,A,B,C,D,15); + + SHA_MIX( 0, 13, 8, 2); SHA_RND1(D,E,A,B,C, 0); + SHA_MIX( 1, 14, 9, 3); SHA_RND1(C,D,E,A,B, 1); + SHA_MIX( 2, 15, 10, 4); SHA_RND1(B,C,D,E,A, 2); + SHA_MIX( 3, 0, 11, 5); SHA_RND1(A,B,C,D,E, 3); + + SHA_MIX( 4, 1, 12, 6); SHA_RND2(E,A,B,C,D, 4); + SHA_MIX( 5, 2, 13, 7); SHA_RND2(D,E,A,B,C, 5); + SHA_MIX( 6, 3, 14, 8); SHA_RND2(C,D,E,A,B, 6); + SHA_MIX( 7, 4, 15, 9); SHA_RND2(B,C,D,E,A, 7); + SHA_MIX( 8, 5, 0, 10); SHA_RND2(A,B,C,D,E, 8); + SHA_MIX( 9, 6, 1, 11); SHA_RND2(E,A,B,C,D, 9); + SHA_MIX(10, 7, 2, 12); SHA_RND2(D,E,A,B,C,10); + SHA_MIX(11, 8, 3, 13); SHA_RND2(C,D,E,A,B,11); + SHA_MIX(12, 9, 4, 14); SHA_RND2(B,C,D,E,A,12); + SHA_MIX(13, 10, 5, 15); SHA_RND2(A,B,C,D,E,13); + SHA_MIX(14, 11, 6, 0); SHA_RND2(E,A,B,C,D,14); + SHA_MIX(15, 12, 7, 1); SHA_RND2(D,E,A,B,C,15); + + SHA_MIX( 0, 13, 8, 2); SHA_RND2(C,D,E,A,B, 0); + SHA_MIX( 1, 14, 9, 3); SHA_RND2(B,C,D,E,A, 1); + SHA_MIX( 2, 15, 10, 4); SHA_RND2(A,B,C,D,E, 2); + SHA_MIX( 3, 0, 11, 5); SHA_RND2(E,A,B,C,D, 3); + SHA_MIX( 4, 1, 12, 6); SHA_RND2(D,E,A,B,C, 4); + SHA_MIX( 5, 2, 13, 7); SHA_RND2(C,D,E,A,B, 5); + SHA_MIX( 6, 3, 14, 8); SHA_RND2(B,C,D,E,A, 6); + SHA_MIX( 7, 4, 15, 9); SHA_RND2(A,B,C,D,E, 7); + + SHA_MIX( 8, 5, 0, 10); SHA_RND3(E,A,B,C,D, 8); + SHA_MIX( 9, 6, 1, 11); SHA_RND3(D,E,A,B,C, 9); + SHA_MIX(10, 7, 2, 12); SHA_RND3(C,D,E,A,B,10); + SHA_MIX(11, 8, 3, 13); SHA_RND3(B,C,D,E,A,11); + SHA_MIX(12, 9, 4, 14); SHA_RND3(A,B,C,D,E,12); + SHA_MIX(13, 10, 5, 15); SHA_RND3(E,A,B,C,D,13); + SHA_MIX(14, 11, 6, 0); SHA_RND3(D,E,A,B,C,14); + SHA_MIX(15, 12, 7, 1); SHA_RND3(C,D,E,A,B,15); + + SHA_MIX( 0, 13, 8, 2); SHA_RND3(B,C,D,E,A, 0); + SHA_MIX( 1, 14, 9, 3); SHA_RND3(A,B,C,D,E, 1); + SHA_MIX( 2, 15, 10, 4); SHA_RND3(E,A,B,C,D, 2); + SHA_MIX( 3, 0, 11, 5); SHA_RND3(D,E,A,B,C, 3); + SHA_MIX( 4, 1, 12, 6); SHA_RND3(C,D,E,A,B, 4); + SHA_MIX( 5, 2, 13, 7); SHA_RND3(B,C,D,E,A, 5); + SHA_MIX( 6, 3, 14, 8); SHA_RND3(A,B,C,D,E, 6); + SHA_MIX( 7, 4, 15, 9); SHA_RND3(E,A,B,C,D, 7); + SHA_MIX( 8, 5, 0, 10); SHA_RND3(D,E,A,B,C, 8); + SHA_MIX( 9, 6, 1, 11); SHA_RND3(C,D,E,A,B, 9); + SHA_MIX(10, 7, 2, 12); SHA_RND3(B,C,D,E,A,10); + SHA_MIX(11, 8, 3, 13); SHA_RND3(A,B,C,D,E,11); + + SHA_MIX(12, 9, 4, 14); SHA_RND4(E,A,B,C,D,12); + SHA_MIX(13, 10, 5, 15); SHA_RND4(D,E,A,B,C,13); + SHA_MIX(14, 11, 6, 0); SHA_RND4(C,D,E,A,B,14); + SHA_MIX(15, 12, 7, 1); SHA_RND4(B,C,D,E,A,15); + + SHA_MIX( 0, 13, 8, 2); SHA_RND4(A,B,C,D,E, 0); + SHA_MIX( 1, 14, 9, 3); SHA_RND4(E,A,B,C,D, 1); + SHA_MIX( 2, 15, 10, 4); SHA_RND4(D,E,A,B,C, 2); + SHA_MIX( 3, 0, 11, 5); SHA_RND4(C,D,E,A,B, 3); + SHA_MIX( 4, 1, 12, 6); SHA_RND4(B,C,D,E,A, 4); + SHA_MIX( 5, 2, 13, 7); SHA_RND4(A,B,C,D,E, 5); + SHA_MIX( 6, 3, 14, 8); SHA_RND4(E,A,B,C,D, 6); + SHA_MIX( 7, 4, 15, 9); SHA_RND4(D,E,A,B,C, 7); + SHA_MIX( 8, 5, 0, 10); SHA_RND4(C,D,E,A,B, 8); + SHA_MIX( 9, 6, 1, 11); SHA_RND4(B,C,D,E,A, 9); + SHA_MIX(10, 7, 2, 12); SHA_RND4(A,B,C,D,E,10); + SHA_MIX(11, 8, 3, 13); SHA_RND4(E,A,B,C,D,11); + SHA_MIX(12, 9, 4, 14); SHA_RND4(D,E,A,B,C,12); + SHA_MIX(13, 10, 5, 15); SHA_RND4(C,D,E,A,B,13); + SHA_MIX(14, 11, 6, 0); SHA_RND4(B,C,D,E,A,14); + SHA_MIX(15, 12, 7, 1); SHA_RND4(A,B,C,D,E,15); + + XH(0) += A; + XH(1) += B; + XH(2) += C; + XH(3) += D; + XH(4) += E; } /************************************************************************* @@ -358,11 +404,13 @@ SHA1_NewContext(void) return cx; } +/* Zero and free the context */ void SHA1_DestroyContext(SHA1Context *cx, PRBool freeit) { + memset(cx, 0, sizeof *cx); if (freeit) { - PORT_ZFree(cx, sizeof(SHA1Context)); + PORT_Free(cx); } } @@ -375,7 +423,6 @@ SHA1_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length) SHA1_Begin(&ctx); SHA1_Update(&ctx, src, src_length); SHA1_End(&ctx, dest, &outLen, SHA1_LENGTH); - return SECSuccess; } @@ -413,38 +460,13 @@ SHA1_Resurrect(unsigned char *space,void *arg) return cx; } +void SHA1_Clone(SHA1Context *dest, SHA1Context *src) +{ + memcpy(dest, src, sizeof *dest); +} + void SHA1_TraceState(SHA1Context *ctx) { -#ifdef TRACING_SSL - uint32 W; - int i; - int len; - int fixWord = -1; - int remainder; /* bytes in last word */ - unsigned char buf[64 * 4]; - - SSL_TRC(99, ("%d: SSL: SHA1 state: %08x %08x %08x %08x %08x", SSL_GETPID(), - ctx->H[0], ctx->H[1], ctx->H[2], ctx->H[3], ctx->H[4])); - - len = (int)(ctx->sizeLo & 63); - remainder = len % 4; - if (remainder) - fixWord = len - remainder; - for (i = 0; i < len; i++) { - if (0 == (i % 4)) { - W = ctx->W[i / 4]; - if (i == fixWord) { - W <<= 8 * (4 - remainder); - } - } - buf[i] = (unsigned char)(W >> 24); - W <<= 8; - } - - PRINT_BUF(99, (0, "SHA1_TraceState: buffered input", buf, len)); - -#else PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); -#endif } diff --git a/security/nss/lib/freebl/sha_fast.h b/security/nss/lib/freebl/sha_fast.h index d92c374f6..6243471b0 100644 --- a/security/nss/lib/freebl/sha_fast.h +++ b/security/nss/lib/freebl/sha_fast.h @@ -37,24 +37,142 @@ #ifndef _SHA_FAST_H_ #define _SHA_FAST_H_ +#include "prlong.h" + #define SHA1_INPUT_LEN 64 +#if defined(IS_64) && !defined(__sparc) +typedef PRUint64 SHA_HW_t; +#define SHA1_USING_64_BIT 1 +#else +typedef PRUint32 SHA_HW_t; +#endif + struct SHA1ContextStr { union { - PRUint32 w[80]; /* input buffer, plus 64 words */ - PRUint8 b[320]; + PRUint32 w[16]; /* input buffer */ + PRUint8 b[64]; } u; - PRUint32 H[5]; /* 5 state variables */ - PRUint32 sizeHi,sizeLo; /* 64-bit count of hashed bytes. */ + PRUint64 size; /* count of hashed bytes. */ + SHA_HW_t H[22]; /* 5 state variables, 16 tmp values, 1 extra */ }; +#if defined(_MSC_VER) && defined(_X86_) +#if defined(IS_LITTLE_ENDIAN) +#ifndef FORCEINLINE +#if (_MSC_VER >= 1200) +#define FORCEINLINE __forceinline +#else +#define FORCEINLINE __inline +#endif /* _MSC_VER */ +#endif /* !defined FORCEINLINE */ +#define FASTCALL __fastcall + +static FORCEINLINE PRUint32 FASTCALL +swap4b(PRUint32 dwd) +{ + __asm { + mov eax,dwd + bswap eax + } +} + +#define SHA_HTONL(x) swap4b(x) +#endif /* IS_LITTLE_ENDIAN */ + +#pragma intrinsic (_lrotr, _lrotl) +#define SHA_ROTL(x,n) _lrotl(x,n) +#define SHA_ROTL_IS_DEFINED 1 +#endif /* _MSC_VER && _X86_ */ + +#if defined(__GNUC__) +/* __x86_64__ and __x86_64 are defined by GCC on x86_64 CPUs */ + +#if defined( SHA1_USING_64_BIT ) +static __inline__ PRUint64 SHA_ROTL(PRUint64 x, PRUint32 n) +{ + PRUint32 t = (PRUint32)x; + return ((t << n) | (t >> (32 - n))); +} +#else +static __inline__ PRUint32 SHA_ROTL(PRUint32 t, PRUint32 n) +{ + return ((t << n) | (t >> (32 - n))); +} +#endif +#define SHA_ROTL_IS_DEFINED 1 + +#if defined(_X86_) || defined(__x86_64__) || defined(__x86_64) +static __inline__ PRUint32 swap4b(PRUint32 value) +{ + __asm__("bswap %0" : "+r" (value)); + return (value); +} +#define SHA_HTONL(x) swap4b(x) +#endif /* x86 family */ + +#endif /* __GNUC__ */ + +#if !defined(SHA_ROTL_IS_DEFINED) +#define SHA_NEED_TMP_VARIABLE 1 +#define SHA_ROTL(X,n) (tmp = (X), ((tmp) << (n)) | ((tmp) >> (32-(n)))) +#endif + +#if defined(_X86_) || defined(__x86_64__) || defined(__x86_64) +#define SHA_ALLOW_UNALIGNED_ACCESS 1 +#endif + +#if !defined(SHA_HTONL) #define SHA_MASK 0x00FF00FF #if defined(IS_LITTLE_ENDIAN) -#define SHA_HTONL(x) (A = (x), A = (A << 16) | (A >> 16), \ - ((A & SHA_MASK) << 8) | ((A >> 8) & SHA_MASK)) +#undef SHA_NEED_TMP_VARIABLE +#define SHA_NEED_TMP_VARIABLE 1 +#define SHA_HTONL(x) (tmp = (x), tmp = (tmp << 16) | (tmp >> 16), \ + ((tmp & SHA_MASK) << 8) | ((tmp >> 8) & SHA_MASK)) #else #define SHA_HTONL(x) (x) #endif +#endif + #define SHA_BYTESWAP(x) x = SHA_HTONL(x) +#define SHA_STORE(n) ((PRUint32*)hashout)[n] = SHA_HTONL(ctx->H[n]) +#if defined(SHA_ALLOW_UNALIGNED_ACCESS) +#define SHA_STORE_RESULT \ + SHA_STORE(0); \ + SHA_STORE(1); \ + SHA_STORE(2); \ + SHA_STORE(3); \ + SHA_STORE(4); + +#elif defined(IS_LITTLE_ENDIAN) || defined( SHA1_USING_64_BIT ) +#define SHA_STORE_RESULT \ + if (!((ptrdiff_t)hashout % sizeof(PRUint32))) { \ + SHA_STORE(0); \ + SHA_STORE(1); \ + SHA_STORE(2); \ + SHA_STORE(3); \ + SHA_STORE(4); \ + } else { \ + ctx->u.w[0] = SHA_HTONL(ctx->H[0]); \ + ctx->u.w[1] = SHA_HTONL(ctx->H[1]); \ + ctx->u.w[2] = SHA_HTONL(ctx->H[2]); \ + ctx->u.w[3] = SHA_HTONL(ctx->H[3]); \ + ctx->u.w[4] = SHA_HTONL(ctx->H[4]); \ + memcpy(hashout, ctx->u.w, SHA1_LENGTH); \ + } + +#else +#define SHA_STORE_RESULT \ + if (!((ptrdiff_t)hashout % sizeof(PRUint32))) { \ + SHA_STORE(0); \ + SHA_STORE(1); \ + SHA_STORE(2); \ + SHA_STORE(3); \ + SHA_STORE(4); \ + } else { \ + memcpy(hashout, ctx->H, SHA1_LENGTH); \ + } +#endif + #endif /* _SHA_FAST_H_ */ diff --git a/security/nss/lib/freebl/tlsprfalg.c b/security/nss/lib/freebl/tlsprfalg.c new file mode 100644 index 000000000..05f3f0d76 --- /dev/null +++ b/security/nss/lib/freebl/tlsprfalg.c @@ -0,0 +1,164 @@ +/* tlsprfalg.c - TLS Pseudo Random Function (PRF) implementation + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* $Id$ */ + +#include "sechash.h" +#include "alghmac.h" +#include "blapi.h" + +#define PHASH_STATE_MAX_LEN SHA1_LENGTH + +/* TLS P_hash function */ +static SECStatus +sftk_P_hash(HASH_HashType hashType, const SECItem *secret, const char *label, + SECItem *seed, SECItem *result, PRBool isFIPS) +{ + unsigned char state[PHASH_STATE_MAX_LEN]; + unsigned char outbuf[PHASH_STATE_MAX_LEN]; + unsigned int state_len = 0, label_len = 0, outbuf_len = 0, chunk_size; + unsigned int remaining; + unsigned char *res; + SECStatus status; + HMACContext *cx; + SECStatus rv = SECFailure; + const SECHashObject *hashObj = HASH_GetRawHashObject(hashType); + + PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len)); + PORT_Assert((seed != NULL) && (seed->data != NULL)); + PORT_Assert((result != NULL) && (result->data != NULL)); + + remaining = result->len; + res = result->data; + + if (label != NULL) + label_len = PORT_Strlen(label); + + cx = HMAC_Create(hashObj, secret->data, secret->len, isFIPS); + if (cx == NULL) + goto loser; + + /* initialize the state = A(1) = HMAC_hash(secret, seed) */ + HMAC_Begin(cx); + HMAC_Update(cx, (unsigned char *)label, label_len); + HMAC_Update(cx, seed->data, seed->len); + status = HMAC_Finish(cx, state, &state_len, sizeof(state)); + if (status != SECSuccess) + goto loser; + + /* generate a block at a time until we're done */ + while (remaining > 0) { + + HMAC_Begin(cx); + HMAC_Update(cx, state, state_len); + if (label_len) + HMAC_Update(cx, (unsigned char *)label, label_len); + HMAC_Update(cx, seed->data, seed->len); + status = HMAC_Finish(cx, outbuf, &outbuf_len, sizeof(outbuf)); + if (status != SECSuccess) + goto loser; + + /* Update the state = A(i) = HMAC_hash(secret, A(i-1)) */ + HMAC_Begin(cx); + HMAC_Update(cx, state, state_len); + status = HMAC_Finish(cx, state, &state_len, sizeof(state)); + if (status != SECSuccess) + goto loser; + + chunk_size = PR_MIN(outbuf_len, remaining); + PORT_Memcpy(res, &outbuf, chunk_size); + res += chunk_size; + remaining -= chunk_size; + } + + rv = SECSuccess; + +loser: + /* clear out state so it's not left on the stack */ + if (cx) + HMAC_Destroy(cx, PR_TRUE); + PORT_Memset(state, 0, sizeof(state)); + PORT_Memset(outbuf, 0, sizeof(outbuf)); + return rv; +} + +SECStatus +TLS_PRF(const SECItem *secret, const char *label, SECItem *seed, + SECItem *result, PRBool isFIPS) +{ + SECStatus rv = SECFailure, status; + unsigned int i; + SECItem tmp = { siBuffer, NULL, 0}; + SECItem S1; + SECItem S2; + + PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len)); + PORT_Assert((seed != NULL) && (seed->data != NULL)); + PORT_Assert((result != NULL) && (result->data != NULL)); + + S1.type = siBuffer; + S1.len = (secret->len / 2) + (secret->len & 1); + S1.data = secret->data; + + S2.type = siBuffer; + S2.len = S1.len; + S2.data = secret->data + (secret->len - S2.len); + + tmp.data = (unsigned char*)PORT_Alloc(result->len); + if (tmp.data == NULL) + goto loser; + tmp.len = result->len; + + status = sftk_P_hash(HASH_AlgMD5, &S1, label, seed, result, isFIPS); + if (status != SECSuccess) + goto loser; + + status = sftk_P_hash(HASH_AlgSHA1, &S2, label, seed, &tmp, isFIPS); + if (status != SECSuccess) + goto loser; + + for (i = 0; i < result->len; i++) + result->data[i] ^= tmp.data[i]; + + rv = SECSuccess; + +loser: + if (tmp.data != NULL) + PORT_ZFree(tmp.data, tmp.len); + return rv; +} + diff --git a/security/nss/lib/manifest.mn b/security/nss/lib/manifest.mn index 108f188f0..268ff0496 100644 --- a/security/nss/lib/manifest.mn +++ b/security/nss/lib/manifest.mn @@ -47,7 +47,6 @@ DEPTH = ../.. # smime # ckfw (builtins module) # crmf jar (not dll's) -# fortcrypt DIRS = util freebl softoken \ base asn1 dev pki pki1 \ certdb certhigh pk11wrap cryptohi nss \ @@ -55,9 +54,10 @@ DIRS = util freebl softoken \ pkcs12 pkcs7 smime \ crmf jar \ ckfw \ - fortcrypt \ $(NULL) +# fortcrypt is no longer built + # NSS 4.0 build - pure stan libraries ifdef PURE_STAN_BUILD DIRS = base asn1 dev pki pki1 diff --git a/security/nss/lib/nss/config.mk b/security/nss/lib/nss/config.mk index 0e70604d7..5cdb444e5 100644 --- a/security/nss/lib/nss/config.mk +++ b/security/nss/lib/nss/config.mk @@ -54,6 +54,7 @@ ifdef NS_USE_GCC EXTRA_SHARED_LIBS += \ -L$(DIST)/lib \ -lsoftokn3 \ + -L$(NSPR_LIB_DIR) \ -lplc4 \ -lplds4 \ -lnspr4\ @@ -61,9 +62,9 @@ EXTRA_SHARED_LIBS += \ else # ! NS_USE_GCC EXTRA_SHARED_LIBS += \ $(DIST)/lib/softokn3.lib \ - $(DIST)/lib/$(NSPR31_LIB_PREFIX)plc4.lib \ - $(DIST)/lib/$(NSPR31_LIB_PREFIX)plds4.lib \ - $(DIST)/lib/$(NSPR31_LIB_PREFIX)nspr4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \ $(NULL) endif # NS_USE_GCC @@ -72,8 +73,9 @@ else # $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS) # $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX. EXTRA_SHARED_LIBS += \ - -L$(DIST)/lib/ \ + -L$(DIST)/lib \ -lsoftokn3 \ + -L$(NSPR_LIB_DIR) \ -lplc4 \ -lplds4 \ -lnspr4 \ diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def index 208638a77..b02dd61ef 100644 --- a/security/nss/lib/nss/nss.def +++ b/security/nss/lib/nss/nss.def @@ -857,3 +857,18 @@ PK11_GenerateKeyPairWithFlags; ;+ local: ;+ *; ;+}; +;+NSS_3.11 { # NSS 3.11 release +;+ global: +CERT_CompareValidityTimes; +PK11_CopyTokenPrivKeyToSessionPrivKey; +PK11_FreeSlotListElement; +PK11_GenerateRandomOnSlot; +PK11_GetSymKeyUserData; +PK11_MapSignKeyType; +PK11_SetSymKeyUserData; +SECMOD_CloseUserDB; +SECMOD_HasRootCerts; +SECMOD_OpenUserDB; +;+ local: +;+ *; +;+}; diff --git a/security/nss/lib/nss/nss.h b/security/nss/lib/nss/nss.h index 0a5ed026c..9ced4592a 100644 --- a/security/nss/lib/nss/nss.h +++ b/security/nss/lib/nss/nss.h @@ -52,11 +52,11 @@ SEC_BEGIN_PROTOS * The format of the version string should be * "<major version>.<minor version>[.<patch level>] [<Beta>]" */ -#define NSS_VERSION "3.10.2" +#define NSS_VERSION "3.11.1 Beta" #define NSS_VMAJOR 3 -#define NSS_VMINOR 10 -#define NSS_VPATCH 2 -#define NSS_BETA PR_FALSE +#define NSS_VMINOR 11 +#define NSS_VPATCH 1 +#define NSS_BETA PR_TRUE /* @@ -119,6 +119,36 @@ extern SECStatus NSS_InitReadWrite(const char *configdir); * NSS_INIT_NOROOTINIT - Don't try to look for the root certs module * automatically. * NSS_INIT_OPTIMIZESPACE - Use smaller tables and caches. + * NSS_INIT_PK11THREADSAFE - only load PKCS#11 modules that are + * thread-safe, ie. that support locking - either OS + * locking or NSS-provided locks . If a PKCS#11 + * module isn't thread-safe, don't serialize its + * calls; just don't load it instead. This is necessary + * if another piece of code is using the same PKCS#11 + * modules that NSS is accessing without going through + * NSS, for example the Java SunPKCS11 provider. + * NSS_INIT_PK11RELOAD - ignore the CKR_CRYPTOKI_ALREADY_INITIALIZED + * error when loading PKCS#11 modules. This is necessary + * if another piece of code is using the same PKCS#11 + * modules that NSS is accessing without going through + * NSS, for example Java SunPKCS11 provider. + * NSS_INIT_NOPK11FINALIZE - never call C_Finalize on any + * PKCS#11 module. This may be necessary in order to + * ensure continuous operation and proper shutdown + * sequence if another piece of code is using the same + * PKCS#11 modules that NSS is accessing without going + * through NSS, for example Java SunPKCS11 provider. + * The following limitation applies when this is set : + * SECMOD_WaitForAnyTokenEvent will not use + * C_WaitForSlotEvent, in order to prevent the need for + * C_Finalize. This call will be emulated instead. + * NSS_INIT_RESERVED - Currently has no effect, but may be used in the + * future to trigger better cooperation between PKCS#11 + * modules used by both NSS and the Java SunPKCS11 + * provider. This should occur after a new flag is defined + * for C_Initialize by the PKCS#11 working group. + * NSS_INIT_COOPERATE - Sets 4 recommended options for applications that + * use both NSS and the Java SunPKCS11 provider. * * Also NOTE: This is not the recommended method for initializing NSS. * The prefered method is NSS_init(). @@ -129,6 +159,15 @@ extern SECStatus NSS_InitReadWrite(const char *configdir); #define NSS_INIT_FORCEOPEN 0x8 #define NSS_INIT_NOROOTINIT 0x10 #define NSS_INIT_OPTIMIZESPACE 0x20 +#define NSS_INIT_PK11THREADSAFE 0x40 +#define NSS_INIT_PK11RELOAD 0x80 +#define NSS_INIT_NOPK11FINALIZE 0x100 +#define NSS_INIT_RESERVED 0x200 + +#define NSS_INIT_COOPERATE NSS_INIT_PK11THREADSAFE | \ + NSS_INIT_PK11RELOAD | \ + NSS_INIT_NOPK11FINALIZE | \ + NSS_INIT_RESERVED #ifdef macintosh #define SECMOD_DB "Security Modules" diff --git a/security/nss/lib/nss/nssinit.c b/security/nss/lib/nss/nssinit.c index a7693b55c..adf3efb04 100644 --- a/security/nss/lib/nss/nssinit.c +++ b/security/nss/lib/nss/nssinit.c @@ -285,7 +285,7 @@ done: static const char *dllname = #if defined(XP_WIN32) || defined(XP_OS2) "nssckbi.dll"; -#elif defined(HPUX) +#elif defined(HPUX) && !defined(__ia64) /* HP-UX PA-RISC */ "libnssckbi.sl"; #elif defined(DARWIN) "libnssckbi.dylib"; @@ -400,7 +400,9 @@ static SECStatus nss_Init(const char *configdir, const char *certPrefix, const char *keyPrefix, const char *secmodName, PRBool readOnly, PRBool noCertDB, PRBool noModDB, PRBool forceOpen, PRBool noRootInit, - PRBool optimizeSpace) + PRBool optimizeSpace, PRBool noSingleThreadedModules, + PRBool allowAlreadyInitializedModules, + PRBool dontFinalizeModules) { char *moduleSpec = NULL; char *flags = NULL; @@ -442,6 +444,12 @@ nss_Init(const char *configdir, const char *certPrefix, const char *keyPrefix, if (lsecmodName == NULL) { goto loser; } + if (noSingleThreadedModules || allowAlreadyInitializedModules || + dontFinalizeModules) { + pk11_setGlobalOptions(noSingleThreadedModules, + allowAlreadyInitializedModules, + dontFinalizeModules); + } moduleSpec = PR_smprintf("name=\"%s\" parameters=\"configdir='%s' certPrefix='%s' keyPrefix='%s' secmod='%s' flags=%s %s\" NSS=\"flags=internal,moduleDB,moduleDBOnly,critical\"", pk11_config_name ? pk11_config_name : NSS_DEFAULT_MOD_NAME, @@ -493,14 +501,14 @@ SECStatus NSS_Init(const char *configdir) { return nss_Init(configdir, "", "", SECMOD_DB, PR_TRUE, - PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE, PR_TRUE); + PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE, PR_TRUE, PR_FALSE, PR_FALSE, PR_FALSE); } SECStatus NSS_InitReadWrite(const char *configdir) { return nss_Init(configdir, "", "", SECMOD_DB, PR_FALSE, - PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE, PR_TRUE); + PR_FALSE, PR_FALSE, PR_FALSE, PR_FALSE, PR_TRUE, PR_FALSE, PR_FALSE, PR_FALSE); } /* @@ -520,6 +528,36 @@ NSS_InitReadWrite(const char *configdir) * initialize the PKCS #11 module. * NSS_INIT_FORCEOPEN - Continue to force initializations even if the * databases cannot be opened. + * NSS_INIT_PK11THREADSAFE - only load PKCS#11 modules that are + * thread-safe, ie. that support locking - either OS + * locking or NSS-provided locks . If a PKCS#11 + * module isn't thread-safe, don't serialize its + * calls; just don't load it instead. This is necessary + * if another piece of code is using the same PKCS#11 + * modules that NSS is accessing without going through + * NSS, for example the Java SunPKCS11 provider. + * NSS_INIT_PK11RELOAD - ignore the CKR_CRYPTOKI_ALREADY_INITIALIZED + * error when loading PKCS#11 modules. This is necessary + * if another piece of code is using the same PKCS#11 + * modules that NSS is accessing without going through + * NSS, for example Java SunPKCS11 provider. + * NSS_INIT_NOPK11FINALIZE - never call C_Finalize on any + * PKCS#11 module. This may be necessary in order to + * ensure continuous operation and proper shutdown + * sequence if another piece of code is using the same + * PKCS#11 modules that NSS is accessing without going + * through NSS, for example Java SunPKCS11 provider. + * The following limitation applies when this is set : + * SECMOD_WaitForAnyTokenEvent will not use + * C_WaitForSlotEvent, in order to prevent the need for + * C_Finalize. This call will be emulated instead. + * NSS_INIT_RESERVED - Currently has no effect, but may be used in the + * future to trigger better cooperation between PKCS#11 + * modules used by both NSS and the Java SunPKCS11 + * provider. This should occur after a new flag is defined + * for C_Initialize by the PKCS#11 working group. + * NSS_INIT_COOPERATE - Sets 4 recommended options for applications that + * use both NSS and the Java SunPKCS11 provider. */ SECStatus NSS_Initialize(const char *configdir, const char *certPrefix, @@ -531,7 +569,10 @@ NSS_Initialize(const char *configdir, const char *certPrefix, ((flags & NSS_INIT_NOMODDB) == NSS_INIT_NOMODDB), ((flags & NSS_INIT_FORCEOPEN) == NSS_INIT_FORCEOPEN), ((flags & NSS_INIT_NOROOTINIT) == NSS_INIT_NOROOTINIT), - ((flags & NSS_INIT_OPTIMIZESPACE) == NSS_INIT_OPTIMIZESPACE)); + ((flags & NSS_INIT_OPTIMIZESPACE) == NSS_INIT_OPTIMIZESPACE), + ((flags & NSS_INIT_PK11THREADSAFE) == NSS_INIT_PK11THREADSAFE), + ((flags & NSS_INIT_PK11RELOAD) == NSS_INIT_PK11RELOAD), + ((flags & NSS_INIT_NOPK11FINALIZE) == NSS_INIT_NOPK11FINALIZE)); } /* @@ -541,7 +582,8 @@ SECStatus NSS_NoDB_Init(const char * configdir) { return nss_Init("","","","", - PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE); + PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE,PR_TRUE, + PR_FALSE,PR_FALSE,PR_FALSE); } extern const NSSError NSS_ERROR_BUSY; diff --git a/security/nss/lib/pk11wrap/manifest.mn b/security/nss/lib/pk11wrap/manifest.mn index fca5fb7b2..b0de09bec 100644 --- a/security/nss/lib/pk11wrap/manifest.mn +++ b/security/nss/lib/pk11wrap/manifest.mn @@ -86,8 +86,3 @@ LIBRARY_NAME = pk11wrap ifdef DEBUG_PKCS11 DEFINES += -DDEBUG_MODULE endif - -ifdef NSS_ENABLE_ECC -DEFINES += -DNSS_ENABLE_ECC -endif - diff --git a/security/nss/lib/pk11wrap/pk11akey.c b/security/nss/lib/pk11wrap/pk11akey.c index 55db33995..a6189cf43 100644 --- a/security/nss/lib/pk11wrap/pk11akey.c +++ b/security/nss/lib/pk11wrap/pk11akey.c @@ -59,10 +59,6 @@ #include "secpkcs5.h" #include "ec.h" -#define PAIRWISE_SECITEM_TYPE siBuffer -#define PAIRWISE_DIGEST_LENGTH SHA1_LENGTH /* 160-bits */ -#define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */ - /* * import a public key into the desired slot */ @@ -156,7 +152,6 @@ PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey, PK11_SETATTRS(attrs, CKA_VALUE, pubKey->u.dh.publicValue.data, pubKey->u.dh.publicValue.len); attrs++; break; -#ifdef NSS_ENABLE_ECC case ecKey: keyType = CKK_EC; PK11_SETATTRS(attrs, CKA_VERIFY, &cktrue, sizeof(CK_BBOOL));attrs++; @@ -168,7 +163,6 @@ PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey, PK11_SETATTRS(attrs, CKA_EC_POINT, pubKey->u.ec.publicValue.data, pubKey->u.ec.publicValue.len); attrs++; break; -#endif /* NSS_ENABLE_ECC */ default: PORT_SetError( SEC_ERROR_BAD_KEY ); return CK_INVALID_HANDLE; @@ -225,9 +219,7 @@ PK11_ExtractPublicKey(PK11SlotInfo *slot,KeyType keyType,CK_OBJECT_HANDLE id) CK_ATTRIBUTE template[8]; CK_ATTRIBUTE *attrs= template; CK_ATTRIBUTE *modulus,*exponent,*base,*prime,*subprime,*value; -#ifdef NSS_ENABLE_ECC CK_ATTRIBUTE *ecparams; -#endif /* NSS_ENABLE_ECC */ /* if we didn't know the key type, get it */ if (keyType== nullKey) { @@ -246,11 +238,9 @@ PK11_ExtractPublicKey(PK11SlotInfo *slot,KeyType keyType,CK_OBJECT_HANDLE id) case CKK_DH: keyType = dhKey; break; -#ifdef NSS_ENABLE_ECC case CKK_EC: keyType = ecKey; break; -#endif /* NSS_ENABLE_ECC */ default: PORT_SetError( SEC_ERROR_BAD_KEY ); return NULL; @@ -355,7 +345,6 @@ PK11_ExtractPublicKey(PK11SlotInfo *slot,KeyType keyType,CK_OBJECT_HANDLE id) crv = pk11_Attr2SecItem(arena,value,&pubKey->u.dh.publicValue); if (crv != CKR_OK) break; break; -#ifdef NSS_ENABLE_ECC case ecKey: pubKey->u.ec.size = 0; ecparams = attrs; @@ -378,7 +367,6 @@ PK11_ExtractPublicKey(PK11SlotInfo *slot,KeyType keyType,CK_OBJECT_HANDLE id) crv = pk11_Attr2SecItem(arena,value,&pubKey->u.ec.publicValue); if (crv != CKR_OK) break; break; -#endif /* NSS_ENABLE_ECC */ case fortezzaKey: case nullKey: default: @@ -421,9 +409,7 @@ PK11_MakePrivKey(PK11SlotInfo *slot, KeyType keyType, case CKK_DSA: keyType = dsaKey; break; case CKK_DH: keyType = dhKey; break; case CKK_KEA: keyType = fortezzaKey; break; -#ifdef NSS_ENABLE_ECC case CKK_EC: keyType = ecKey; break; -#endif /* NSS_ENABLE_ECC */ default: break; } @@ -507,258 +493,6 @@ PK11_GetPrivateModulusLen(SECKEYPrivateKey *key) return -1; } -/* - * PKCS #11 pairwise consistency check utilized to validate key pair. - */ -static SECStatus -pk11_PairwiseConsistencyCheck(SECKEYPublicKey *pubKey, - SECKEYPrivateKey *privKey, CK_MECHANISM *mech, void* wincx ) -{ - /* Variables used for Encrypt/Decrypt functions. */ - unsigned char *known_message = (unsigned char *)"Known Crypto Message"; - CK_BBOOL isEncryptable = CK_FALSE; - CK_BBOOL canSignVerify = CK_FALSE; - CK_BBOOL isDerivable = CK_FALSE; - unsigned char plaintext[PAIRWISE_MESSAGE_LENGTH]; - CK_ULONG bytes_decrypted; - PK11SlotInfo *slot; - CK_OBJECT_HANDLE id; - unsigned char *ciphertext; - unsigned char *text_compared; - CK_ULONG max_bytes_encrypted; - CK_ULONG bytes_encrypted; - CK_ULONG bytes_compared; - CK_RV crv; - - /* Variables used for Signature/Verification functions. */ - unsigned char *known_digest = (unsigned char *)"Mozilla Rules World!"; - SECItem signature; - SECItem digest; /* always uses SHA-1 digest */ - int signature_length; - SECStatus rv; - - /**************************************************/ - /* Pairwise Consistency Check of Encrypt/Decrypt. */ - /**************************************************/ - - isEncryptable = PK11_HasAttributeSet( privKey->pkcs11Slot, - privKey->pkcs11ID, CKA_DECRYPT ); - - /* If the encryption attribute is set; attempt to encrypt */ - /* with the public key and decrypt with the private key. */ - if( isEncryptable ) { - /* Find a module to encrypt against */ - slot = PK11_GetBestSlot(pk11_mapWrapKeyType(privKey->keyType),wincx); - if (slot == NULL) { - PORT_SetError( SEC_ERROR_NO_MODULE ); - return SECFailure; - } - - id = PK11_ImportPublicKey(slot,pubKey,PR_FALSE); - if (id == CK_INVALID_HANDLE) { - PK11_FreeSlot(slot); - return SECFailure; - } - - /* Compute max bytes encrypted from modulus length of private key. */ - max_bytes_encrypted = PK11_GetPrivateModulusLen( privKey ); - - - /* Prepare for encryption using the public key. */ - PK11_EnterSlotMonitor(slot); - crv = PK11_GETTAB( slot )->C_EncryptInit( slot->session, - mech, id ); - if( crv != CKR_OK ) { - PK11_ExitSlotMonitor(slot); - PORT_SetError( PK11_MapError( crv ) ); - PK11_FreeSlot(slot); - return SECFailure; - } - - /* Allocate space for ciphertext. */ - ciphertext = (unsigned char *) PORT_Alloc( max_bytes_encrypted ); - if( ciphertext == NULL ) { - PK11_ExitSlotMonitor(slot); - PORT_SetError( SEC_ERROR_NO_MEMORY ); - PK11_FreeSlot(slot); - return SECFailure; - } - - /* Initialize bytes encrypted to max bytes encrypted. */ - bytes_encrypted = max_bytes_encrypted; - - /* Encrypt using the public key. */ - crv = PK11_GETTAB( slot )->C_Encrypt( slot->session, - known_message, - PAIRWISE_MESSAGE_LENGTH, - ciphertext, - &bytes_encrypted ); - PK11_ExitSlotMonitor(slot); - PK11_FreeSlot(slot); - if( crv != CKR_OK ) { - PORT_SetError( PK11_MapError( crv ) ); - PORT_Free( ciphertext ); - return SECFailure; - } - - /* Always use the smaller of these two values . . . */ - bytes_compared = ( bytes_encrypted > PAIRWISE_MESSAGE_LENGTH ) - ? PAIRWISE_MESSAGE_LENGTH - : bytes_encrypted; - - /* If there was a failure, the plaintext */ - /* goes at the end, therefore . . . */ - text_compared = ( bytes_encrypted > PAIRWISE_MESSAGE_LENGTH ) - ? (ciphertext + bytes_encrypted - - PAIRWISE_MESSAGE_LENGTH ) - : ciphertext; - - /* Check to ensure that ciphertext does */ - /* NOT EQUAL known input message text */ - /* per FIPS PUB 140-1 directive. */ - if( ( bytes_encrypted != max_bytes_encrypted ) || - ( PORT_Memcmp( text_compared, known_message, - bytes_compared ) == 0 ) ) { - /* Set error to Invalid PRIVATE Key. */ - PORT_SetError( SEC_ERROR_INVALID_KEY ); - PORT_Free( ciphertext ); - return SECFailure; - } - - slot = privKey->pkcs11Slot; - /* Prepare for decryption using the private key. */ - PK11_EnterSlotMonitor(slot); - crv = PK11_GETTAB( slot )->C_DecryptInit( slot->session, - mech, - privKey->pkcs11ID ); - if( crv != CKR_OK ) { - PK11_ExitSlotMonitor(slot); - PORT_SetError( PK11_MapError(crv) ); - PORT_Free( ciphertext ); - return SECFailure; - } - - /* Initialize bytes decrypted to be the */ - /* expected PAIRWISE_MESSAGE_LENGTH. */ - bytes_decrypted = PAIRWISE_MESSAGE_LENGTH; - - /* Decrypt using the private key. */ - /* NOTE: No need to reset the */ - /* value of bytes_encrypted. */ - crv = PK11_GETTAB( slot )->C_Decrypt( slot->session, - ciphertext, - bytes_encrypted, - plaintext, - &bytes_decrypted ); - PK11_ExitSlotMonitor(slot); - - /* Finished with ciphertext; free it. */ - PORT_Free( ciphertext ); - - if( crv != CKR_OK ) { - PORT_SetError( PK11_MapError(crv) ); - return SECFailure; - } - - /* Check to ensure that the output plaintext */ - /* does EQUAL known input message text. */ - if( ( bytes_decrypted != PAIRWISE_MESSAGE_LENGTH ) || - ( PORT_Memcmp( plaintext, known_message, - PAIRWISE_MESSAGE_LENGTH ) != 0 ) ) { - /* Set error to Bad PUBLIC Key. */ - PORT_SetError( SEC_ERROR_BAD_KEY ); - return SECFailure; - } - } - - /**********************************************/ - /* Pairwise Consistency Check of Sign/Verify. */ - /**********************************************/ - - canSignVerify = PK11_HasAttributeSet ( privKey->pkcs11Slot, - privKey->pkcs11ID, CKA_SIGN); - - if (canSignVerify) - { - /* Initialize signature and digest data. */ - signature.data = NULL; - digest.data = NULL; - - /* Determine length of signature. */ - signature_length = PK11_SignatureLen( privKey ); - if( signature_length == 0 ) - goto failure; - - /* Allocate space for signature data. */ - signature.data = (unsigned char *) PORT_Alloc( signature_length ); - if( signature.data == NULL ) { - PORT_SetError( SEC_ERROR_NO_MEMORY ); - goto failure; - } - - /* Allocate space for known digest data. */ - digest.data = (unsigned char *) PORT_Alloc( PAIRWISE_DIGEST_LENGTH ); - if( digest.data == NULL ) { - PORT_SetError( SEC_ERROR_NO_MEMORY ); - goto failure; - } - - /* "Fill" signature type and length. */ - signature.type = PAIRWISE_SECITEM_TYPE; - signature.len = signature_length; - - /* "Fill" digest with known SHA-1 digest parameters. */ - digest.type = PAIRWISE_SECITEM_TYPE; - PORT_Memcpy( digest.data, known_digest, PAIRWISE_DIGEST_LENGTH ); - digest.len = PAIRWISE_DIGEST_LENGTH; - - /* Sign the known hash using the private key. */ - rv = PK11_Sign( privKey, &signature, &digest ); - if( rv != SECSuccess ) - goto failure; - - /* Verify the known hash using the public key. */ - rv = PK11_Verify( pubKey, &signature, &digest, wincx ); - if( rv != SECSuccess ) - goto failure; - - /* Free signature and digest data. */ - PORT_Free( signature.data ); - PORT_Free( digest.data ); - } - - - - /**********************************************/ - /* Pairwise Consistency Check for Derivation */ - /**********************************************/ - - isDerivable = PK11_HasAttributeSet ( privKey->pkcs11Slot, - privKey->pkcs11ID, CKA_DERIVE); - - if (isDerivable) - { - /* - * We are not doing consistency check for Diffie-Hellman Key - - * otherwise it would be here - * This is also true for Elliptic Curve Diffie-Hellman keys - * NOTE: EC keys are currently subjected to pairwise - * consistency check for signing/verification. - */ - - } - - return SECSuccess; - -failure: - if( signature.data != NULL ) - PORT_Free( signature.data ); - if( digest.data != NULL ) - PORT_Free( digest.data ); - - return SECFailure; -} - /* @@ -846,12 +580,10 @@ pk11_loadPrivKeyWithFlags(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, ap->type = CKA_BASE; ap++; count++; extra_count++; ap->type = CKA_VALUE; ap++; count++; extra_count++; break; -#ifdef NSS_ENABLE_ECC case ecKey: ap->type = CKA_EC_PARAMS; ap++; count++; extra_count++; ap->type = CKA_VALUE; ap++; count++; extra_count++; break; -#endif /* NSS_ENABLE_ECC */ default: count = 0; extra_count = 0; @@ -909,135 +641,22 @@ pk11_loadPrivKeyWithFlags(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, objectID, privKey->wincx); } -SECKEYPrivateKey * +static SECKEYPrivateKey * pk11_loadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, PRBool token, PRBool sensitive) { - CK_ATTRIBUTE privTemplate[] = { - /* class must be first */ - { CKA_CLASS, NULL, 0 }, - { CKA_KEY_TYPE, NULL, 0 }, - /* these three must be next */ - { CKA_TOKEN, NULL, 0 }, - { CKA_PRIVATE, NULL, 0 }, - { CKA_SENSITIVE, NULL, 0 }, - { CKA_ID, NULL, 0 }, -#ifdef notdef - { CKA_LABEL, NULL, 0 }, - { CKA_SUBJECT, NULL, 0 }, -#endif - /* RSA */ - { CKA_MODULUS, NULL, 0 }, - { CKA_PRIVATE_EXPONENT, NULL, 0 }, - { CKA_PUBLIC_EXPONENT, NULL, 0 }, - { CKA_PRIME_1, NULL, 0 }, - { CKA_PRIME_2, NULL, 0 }, - { CKA_EXPONENT_1, NULL, 0 }, - { CKA_EXPONENT_2, NULL, 0 }, - { CKA_COEFFICIENT, NULL, 0 }, - }; - CK_ATTRIBUTE *attrs = NULL, *ap; - int templateSize = sizeof(privTemplate)/sizeof(privTemplate[0]); - PRArenaPool *arena; - CK_OBJECT_HANDLE objectID; - int i, count = 0; - int extra_count = 0; - CK_RV crv; - SECStatus rv; - - for (i=0; i < templateSize; i++) { - if (privTemplate[i].type == CKA_MODULUS) { - attrs= &privTemplate[i]; - count = i; - break; - } + PK11AttrFlags attrFlags = 0; + if (token) { + attrFlags |= (PK11_ATTR_TOKEN | PK11_ATTR_PRIVATE); + } else { + attrFlags |= (PK11_ATTR_SESSION | PK11_ATTR_PUBLIC); } - PORT_Assert(attrs != NULL); - if (attrs == NULL) { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return NULL; + if (sensitive) { + attrFlags |= PK11_ATTR_SENSITIVE; + } else { + attrFlags |= PK11_ATTR_INSENSITIVE; } - - ap = attrs; - - switch (privKey->keyType) { - case rsaKey: - count = templateSize; - extra_count = templateSize - (attrs - privTemplate); - break; - case dsaKey: - ap->type = CKA_PRIME; ap++; count++; extra_count++; - ap->type = CKA_SUBPRIME; ap++; count++; extra_count++; - ap->type = CKA_BASE; ap++; count++; extra_count++; - ap->type = CKA_VALUE; ap++; count++; extra_count++; - break; - case dhKey: - ap->type = CKA_PRIME; ap++; count++; extra_count++; - ap->type = CKA_BASE; ap++; count++; extra_count++; - ap->type = CKA_VALUE; ap++; count++; extra_count++; - break; -#ifdef NSS_ENABLE_ECC - case ecKey: - ap->type = CKA_EC_PARAMS; ap++; count++; extra_count++; - ap->type = CKA_VALUE; ap++; count++; extra_count++; - break; -#endif /* NSS_ENABLE_ECC */ - default: - count = 0; - extra_count = 0; - break; - } - - if (count == 0) { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return NULL; - } - - arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE); - if (arena == NULL) return NULL; - /* - * read out the old attributes. - */ - crv = PK11_GetAttributes(arena, privKey->pkcs11Slot, privKey->pkcs11ID, - privTemplate,count); - if (crv != CKR_OK) { - PORT_SetError( PK11_MapError(crv) ); - PORT_FreeArena(arena, PR_TRUE); - return NULL; - } - - /* Reset sensitive, token, and private */ - *(CK_BBOOL *)(privTemplate[2].pValue) = token ? CK_TRUE : CK_FALSE; - *(CK_BBOOL *)(privTemplate[3].pValue) = token ? CK_TRUE : CK_FALSE; - *(CK_BBOOL *)(privTemplate[4].pValue) = sensitive ? CK_TRUE : CK_FALSE; - - /* Not everyone can handle zero padded key values, give - * them the raw data as unsigned */ - for (ap=attrs; extra_count; ap++, extra_count--) { - pk11_SignedToUnsigned(ap); - } - - /* now Store the puppies */ - rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, privTemplate, - count, token, &objectID); - PORT_FreeArena(arena, PR_TRUE); - if (rv != SECSuccess) { - return NULL; - } - - /* try loading the public key as a token object */ - if (pubKey) { - PK11_ImportPublicKey(slot, pubKey, PR_TRUE); - if (pubKey->pkcs11Slot) { - PK11_FreeSlot(pubKey->pkcs11Slot); - pubKey->pkcs11Slot = NULL; - pubKey->pkcs11ID = CK_INVALID_HANDLE; - } - } - - /* build new key structure */ - return PK11_MakePrivKey(slot, privKey->keyType, (PRBool)!token, - objectID, privKey->wincx); + return pk11_loadPrivKeyWithFlags(slot, privKey, pubKey, attrFlags); } /* @@ -1110,7 +729,6 @@ PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, { CKA_ENCRYPT, NULL, 0}, { CKA_MODIFIABLE, NULL, 0}, }; -#ifdef NSS_ENABLE_ECC CK_ATTRIBUTE ecPubTemplate[] = { { CKA_EC_PARAMS, NULL, 0 }, { CKA_TOKEN, NULL, 0}, @@ -1122,7 +740,6 @@ PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, { CKA_MODIFIABLE, NULL, 0}, }; SECKEYECParams * ecParams; -#endif /* NSS_ENABLE_ECC */ /*CK_ULONG key_size = 0;*/ CK_ATTRIBUTE *pubTemplate; @@ -1144,7 +761,6 @@ PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, CK_ATTRIBUTE *privattrs; SECItem *pubKeyIndex; CK_ATTRIBUTE setTemplate; - SECStatus rv; CK_MECHANISM_INFO mechanism_info; CK_OBJECT_CLASS keyClass; SECItem *cka_id; @@ -1219,7 +835,12 @@ PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, /* set up the mechanism specific info */ switch (type) { case CKM_RSA_PKCS_KEY_PAIR_GEN: + case CKM_RSA_X9_31_KEY_PAIR_GEN: rsaParams = (PK11RSAGenParams *)param; + if (rsaParams->pe == 0) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return NULL; + } modulusBits = rsaParams->keySizeInBits; peCount = 0; @@ -1266,7 +887,6 @@ PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, keyType = dhKey; test_mech.mechanism = CKM_DH_PKCS_DERIVE; break; -#ifdef NSS_ENABLE_ECC case CKM_EC_KEY_PAIR_GEN: ecParams = (SECKEYECParams *)param; attrs = ecPubTemplate; @@ -1281,7 +901,6 @@ PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, */ test_mech.mechanism = CKM_ECDH1_DERIVE; break; -#endif /* NSS_ENABLE_ECC */ default: PORT_SetError( SEC_ERROR_BAD_KEY ); return NULL; @@ -1305,7 +924,6 @@ PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, case CKM_DH_PKCS_DERIVE: mechanism_info.flags = CKF_DERIVE; break; -#ifdef NSS_ENABLE_ECC case CKM_ECDH1_DERIVE: mechanism_info.flags = CKF_DERIVE; break; @@ -1313,7 +931,6 @@ PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, case CKM_ECDSA_SHA1: mechanism_info.flags = CKF_SIGN | CKF_VERIFY; break; -#endif /* NSS_ENABLE_ECC */ default: break; } @@ -1355,12 +972,17 @@ PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, haslock = PK11_RWSessionHasLock(slot,session_handle); restore = PR_TRUE; } else { - PK11_EnterSlotMonitor(slot); /* gross!! */ session_handle = slot->session; + if (session_handle != CK_INVALID_SESSION) + PK11_EnterSlotMonitor(slot); restore = PR_FALSE; haslock = PR_TRUE; } + if (session_handle == CK_INVALID_SESSION) { + PORT_SetError(SEC_ERROR_BAD_DATA); + return NULL; + } privCount = privattrs - privTemplate; pubCount = attrs - pubTemplate; crv = PK11_GETTAB(slot)->C_GenerateKeyPair(session_handle, &mechanism, @@ -1403,6 +1025,7 @@ PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, pubKeyIndex = NULL; switch (type) { case CKM_RSA_PKCS_KEY_PAIR_GEN: + case CKM_RSA_X9_31_KEY_PAIR_GEN: pubKeyIndex = &(*pubKey)->u.rsa.modulus; break; case CKM_DSA_KEY_PAIR_GEN: @@ -1411,11 +1034,9 @@ PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, case CKM_DH_PKCS_KEY_PAIR_GEN: pubKeyIndex = &(*pubKey)->u.dh.publicValue; break; -#ifdef NSS_ENABLE_ECC case CKM_EC_KEY_PAIR_GEN: pubKeyIndex = &(*pubKey)->u.ec.publicValue; break; -#endif /* NSS_ENABLE_ECC */ } PORT_Assert(pubKeyIndex != NULL); @@ -1458,16 +1079,6 @@ PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, return NULL; } - /* Perform PKCS #11 pairwise consistency check. */ - rv = pk11_PairwiseConsistencyCheck( *pubKey, privKey, &test_mech, wincx ); - if( rv != SECSuccess ) { - SECKEY_DestroyPublicKey( *pubKey ); - SECKEY_DestroyPrivateKey( privKey ); - *pubKey = NULL; - privKey = NULL; - return NULL; /* due to pairwise consistency check */ - } - return privKey; } @@ -1479,410 +1090,20 @@ PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, void *param, SECKEYPublicKey **pubKey, PRBool token, PRBool sensitive, void *wincx) { - /* we have to use these native types because when we call PKCS 11 modules - * we have to make sure that we are using the correct sizes for all the - * parameters. */ - CK_BBOOL ckfalse = CK_FALSE; - CK_BBOOL cktrue = CK_TRUE; - CK_ULONG modulusBits; - CK_BYTE publicExponent[4]; - CK_ATTRIBUTE privTemplate[] = { - { CKA_SENSITIVE, NULL, 0}, - { CKA_TOKEN, NULL, 0}, - { CKA_PRIVATE, NULL, 0}, - { CKA_DERIVE, NULL, 0}, - { CKA_UNWRAP, NULL, 0}, - { CKA_SIGN, NULL, 0}, - { CKA_DECRYPT, NULL, 0}, - }; - CK_ATTRIBUTE rsaPubTemplate[] = { - { CKA_MODULUS_BITS, NULL, 0}, - { CKA_PUBLIC_EXPONENT, NULL, 0}, - { CKA_TOKEN, NULL, 0}, - { CKA_DERIVE, NULL, 0}, - { CKA_WRAP, NULL, 0}, - { CKA_VERIFY, NULL, 0}, - { CKA_VERIFY_RECOVER, NULL, 0}, - { CKA_ENCRYPT, NULL, 0}, - }; - CK_ATTRIBUTE dsaPubTemplate[] = { - { CKA_PRIME, NULL, 0 }, - { CKA_SUBPRIME, NULL, 0 }, - { CKA_BASE, NULL, 0 }, - { CKA_TOKEN, NULL, 0}, - { CKA_DERIVE, NULL, 0}, - { CKA_WRAP, NULL, 0}, - { CKA_VERIFY, NULL, 0}, - { CKA_VERIFY_RECOVER, NULL, 0}, - { CKA_ENCRYPT, NULL, 0}, - }; - CK_ATTRIBUTE dhPubTemplate[] = { - { CKA_PRIME, NULL, 0 }, - { CKA_BASE, NULL, 0 }, - { CKA_TOKEN, NULL, 0}, - { CKA_DERIVE, NULL, 0}, - { CKA_WRAP, NULL, 0}, - { CKA_VERIFY, NULL, 0}, - { CKA_VERIFY_RECOVER, NULL, 0}, - { CKA_ENCRYPT, NULL, 0}, - }; -#ifdef NSS_ENABLE_ECC - CK_ATTRIBUTE ecPubTemplate[] = { - { CKA_EC_PARAMS, NULL, 0 }, - { CKA_TOKEN, NULL, 0}, - { CKA_DERIVE, NULL, 0}, - { CKA_WRAP, NULL, 0}, - { CKA_VERIFY, NULL, 0}, - { CKA_VERIFY_RECOVER, NULL, 0}, - { CKA_ENCRYPT, NULL, 0}, - }; - int ecPubCount = sizeof(ecPubTemplate)/sizeof(ecPubTemplate[0]); - SECKEYECParams * ecParams; -#endif /* NSS_ENABLE_ECC */ - - int dsaPubCount = sizeof(dsaPubTemplate)/sizeof(dsaPubTemplate[0]); - /*CK_ULONG key_size = 0;*/ - CK_ATTRIBUTE *pubTemplate; - int privCount = sizeof(privTemplate)/sizeof(privTemplate[0]); - int rsaPubCount = sizeof(rsaPubTemplate)/sizeof(rsaPubTemplate[0]); - int dhPubCount = sizeof(dhPubTemplate)/sizeof(dhPubTemplate[0]); - int pubCount = 0; - PK11RSAGenParams *rsaParams; - SECKEYPQGParams *dsaParams; - SECKEYDHParams * dhParams; - CK_MECHANISM mechanism; - CK_MECHANISM test_mech; - CK_SESSION_HANDLE session_handle; - CK_RV crv; - CK_OBJECT_HANDLE privID,pubID; - SECKEYPrivateKey *privKey; - KeyType keyType; - PRBool restore; - int peCount,i; - CK_ATTRIBUTE *attrs; - CK_ATTRIBUTE *privattrs; - SECItem *pubKeyIndex; - CK_ATTRIBUTE setTemplate; - SECStatus rv; - CK_MECHANISM_INFO mechanism_info; - CK_OBJECT_CLASS keyClass; - SECItem *cka_id; - PRBool haslock = PR_FALSE; - PRBool pubIsToken = PR_FALSE; - - PORT_Assert(slot != NULL); - if (slot == NULL) { - PORT_SetError( SEC_ERROR_NO_MODULE); - return NULL; - } - - /* if our slot really doesn't do this mechanism, Generate the key - * in our internal token and write it out */ - if (!PK11_DoesMechanism(slot,type)) { - PK11SlotInfo *int_slot = PK11_GetInternalSlot(); - - /* don't loop forever looking for a slot */ - if (slot == int_slot) { - PK11_FreeSlot(int_slot); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return NULL; - } - - /* if there isn't a suitable slot, then we can't do the keygen */ - if (int_slot == NULL) { - PORT_SetError( SEC_ERROR_NO_MODULE ); - return NULL; - } - - /* generate the temporary key to load */ - privKey = PK11_GenerateKeyPair(int_slot,type, param, pubKey, PR_FALSE, - PR_FALSE, wincx); - PK11_FreeSlot(int_slot); - - /* if successful, load the temp key into the new token */ - if (privKey != NULL) { - SECKEYPrivateKey *newPrivKey = pk11_loadPrivKey(slot,privKey, - *pubKey,token,sensitive); - SECKEY_DestroyPrivateKey(privKey); - if (newPrivKey == NULL) { - SECKEY_DestroyPublicKey(*pubKey); - *pubKey = NULL; - } - return newPrivKey; - } - return NULL; - } - - - mechanism.mechanism = type; - mechanism.pParameter = NULL; - mechanism.ulParameterLen = 0; - test_mech.pParameter = NULL; - test_mech.ulParameterLen = 0; - - /* set up the private key template */ - privattrs = privTemplate; - PK11_SETATTRS(privattrs, CKA_SENSITIVE, sensitive ? &cktrue : &ckfalse, - sizeof(CK_BBOOL)); privattrs++; - PK11_SETATTRS(privattrs, CKA_TOKEN, token ? &cktrue : &ckfalse, - sizeof(CK_BBOOL)); privattrs++; - PK11_SETATTRS(privattrs, CKA_PRIVATE, sensitive ? &cktrue : &ckfalse, - sizeof(CK_BBOOL)); privattrs++; - - /* set up the mechanism specific info */ - switch (type) { - case CKM_RSA_PKCS_KEY_PAIR_GEN: - rsaParams = (PK11RSAGenParams *)param; - modulusBits = rsaParams->keySizeInBits; - peCount = 0; - - /* convert pe to a PKCS #11 string */ - for (i=0; i < 4; i++) { - if (peCount || (rsaParams->pe & - ((unsigned long)0xff000000L >> (i*8)))) { - publicExponent[peCount] = - (CK_BYTE)((rsaParams->pe >> (3-i)*8) & 0xff); - peCount++; - } - } - PORT_Assert(peCount != 0); - attrs = rsaPubTemplate; - PK11_SETATTRS(attrs, CKA_MODULUS_BITS, - &modulusBits, sizeof(modulusBits)); attrs++; - PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, - publicExponent, peCount);attrs++; - pubTemplate = rsaPubTemplate; - pubCount = rsaPubCount; - keyType = rsaKey; - test_mech.mechanism = CKM_RSA_PKCS; - break; - case CKM_DSA_KEY_PAIR_GEN: - dsaParams = (SECKEYPQGParams *)param; - attrs = dsaPubTemplate; - PK11_SETATTRS(attrs, CKA_PRIME, dsaParams->prime.data, - dsaParams->prime.len); attrs++; - PK11_SETATTRS(attrs, CKA_SUBPRIME, dsaParams->subPrime.data, - dsaParams->subPrime.len); attrs++; - PK11_SETATTRS(attrs, CKA_BASE, dsaParams->base.data, - dsaParams->base.len); attrs++; - pubTemplate = dsaPubTemplate; - pubCount = dsaPubCount; - keyType = dsaKey; - test_mech.mechanism = CKM_DSA; - break; - case CKM_DH_PKCS_KEY_PAIR_GEN: - dhParams = (SECKEYDHParams *)param; - attrs = dhPubTemplate; - PK11_SETATTRS(attrs, CKA_PRIME, dhParams->prime.data, - dhParams->prime.len); attrs++; - PK11_SETATTRS(attrs, CKA_BASE, dhParams->base.data, - dhParams->base.len); attrs++; - pubTemplate = dhPubTemplate; - pubCount = dhPubCount; - keyType = dhKey; - test_mech.mechanism = CKM_DH_PKCS_DERIVE; - break; -#ifdef NSS_ENABLE_ECC - case CKM_EC_KEY_PAIR_GEN: - ecParams = (SECKEYECParams *)param; - attrs = ecPubTemplate; - PK11_SETATTRS(attrs, CKA_EC_PARAMS, ecParams->data, - ecParams->len); attrs++; - pubTemplate = ecPubTemplate; - pubCount = ecPubCount; - keyType = ecKey; - /* XXX An EC key can be used for other mechanisms too such - * as CKM_ECDSA and CKM_ECDSA_SHA1. How can we reflect - * that in test_mech.mechanism so the CKA_SIGN, CKA_VERIFY - * attributes are set correctly? - */ - test_mech.mechanism = CKM_ECDH1_DERIVE; - break; -#endif /* NSS_ENABLE_ECC */ - default: - PORT_SetError( SEC_ERROR_BAD_KEY ); - return NULL; - } - - /* now query the slot to find out how "good" a key we can generate */ - if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); - crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID, - test_mech.mechanism,&mechanism_info); - if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); - if ((crv != CKR_OK) || (mechanism_info.flags == 0)) { - /* must be old module... guess what it should be... */ - switch (test_mech.mechanism) { - case CKM_RSA_PKCS: - mechanism_info.flags = (CKF_SIGN | CKF_DECRYPT | - CKF_WRAP | CKF_VERIFY_RECOVER | CKF_ENCRYPT | CKF_WRAP);; - break; - case CKM_DSA: - mechanism_info.flags = CKF_SIGN | CKF_VERIFY; - break; - case CKM_DH_PKCS_DERIVE: - mechanism_info.flags = CKF_DERIVE; - break; -#ifdef NSS_ENABLE_ECC - case CKM_ECDH1_DERIVE: - mechanism_info.flags = CKF_DERIVE; - break; - case CKM_ECDSA: - case CKM_ECDSA_SHA1: - mechanism_info.flags = CKF_SIGN | CKF_VERIFY; - break; -#endif /* NSS_ENABLE_ECC */ - default: - break; - } - } - /* set the public key objects */ - PK11_SETATTRS(attrs, CKA_TOKEN, token ? &cktrue : &ckfalse, - sizeof(CK_BBOOL)); attrs++; - PK11_SETATTRS(attrs, CKA_DERIVE, - mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse, - sizeof(CK_BBOOL)); attrs++; - PK11_SETATTRS(attrs, CKA_WRAP, - mechanism_info.flags & CKF_WRAP ? &cktrue : &ckfalse, - sizeof(CK_BBOOL)); attrs++; - PK11_SETATTRS(attrs, CKA_VERIFY, - mechanism_info.flags & CKF_VERIFY ? &cktrue : &ckfalse, - sizeof(CK_BBOOL)); attrs++; - PK11_SETATTRS(attrs, CKA_VERIFY_RECOVER, - mechanism_info.flags & CKF_VERIFY_RECOVER ? &cktrue : &ckfalse, - sizeof(CK_BBOOL)); attrs++; - PK11_SETATTRS(attrs, CKA_ENCRYPT, - mechanism_info.flags & CKF_ENCRYPT? &cktrue : &ckfalse, - sizeof(CK_BBOOL)); attrs++; - PK11_SETATTRS(privattrs, CKA_DERIVE, - mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse, - sizeof(CK_BBOOL)); privattrs++; - PK11_SETATTRS(privattrs, CKA_UNWRAP, - mechanism_info.flags & CKF_UNWRAP ? &cktrue : &ckfalse, - sizeof(CK_BBOOL)); privattrs++; - PK11_SETATTRS(privattrs, CKA_SIGN, - mechanism_info.flags & CKF_SIGN ? &cktrue : &ckfalse, - sizeof(CK_BBOOL)); privattrs++; - PK11_SETATTRS(privattrs, CKA_DECRYPT, - mechanism_info.flags & CKF_DECRYPT ? &cktrue : &ckfalse, - sizeof(CK_BBOOL)); privattrs++; + PK11AttrFlags attrFlags = 0; if (token) { - session_handle = PK11_GetRWSession(slot); - haslock = PK11_RWSessionHasLock(slot,session_handle); - restore = PR_TRUE; + attrFlags |= PK11_ATTR_TOKEN; } else { - PK11_EnterSlotMonitor(slot); /* gross!! */ - session_handle = slot->session; - restore = PR_FALSE; - haslock = PR_TRUE; - } - - crv = PK11_GETTAB(slot)->C_GenerateKeyPair(session_handle, &mechanism, - pubTemplate,pubCount,privTemplate,privCount,&pubID,&privID); - - if (crv != CKR_OK) { - if (restore) { - PK11_RestoreROSession(slot,session_handle); - } else PK11_ExitSlotMonitor(slot); - PORT_SetError( PK11_MapError(crv) ); - return NULL; - } - /* This locking code is dangerous and needs to be more thought - * out... the real problem is that we're holding the mutex open this long - */ - if (haslock) { PK11_ExitSlotMonitor(slot); } - - /* swap around the ID's for older PKCS #11 modules */ - keyClass = PK11_ReadULongAttribute(slot,pubID,CKA_CLASS); - if (keyClass != CKO_PUBLIC_KEY) { - CK_OBJECT_HANDLE tmp = pubID; - pubID = privID; - privID = tmp; - } - - *pubKey = PK11_ExtractPublicKey(slot, keyType, pubID); - if (*pubKey == NULL) { - if (restore) { - /* we may have to restore the mutex so it get's exited properly - * in RestoreROSession */ - if (haslock) PK11_EnterSlotMonitor(slot); - PK11_RestoreROSession(slot,session_handle); - } - PK11_DestroyObject(slot,pubID); - PK11_DestroyObject(slot,privID); - return NULL; - } - - /* set the ID to the public key so we can find it again */ - pubKeyIndex = NULL; - switch (type) { - case CKM_RSA_PKCS_KEY_PAIR_GEN: - pubKeyIndex = &(*pubKey)->u.rsa.modulus; - break; - case CKM_DSA_KEY_PAIR_GEN: - pubKeyIndex = &(*pubKey)->u.dsa.publicValue; - break; - case CKM_DH_PKCS_KEY_PAIR_GEN: - pubKeyIndex = &(*pubKey)->u.dh.publicValue; - break; -#ifdef NSS_ENABLE_ECC - case CKM_EC_KEY_PAIR_GEN: - pubKeyIndex = &(*pubKey)->u.ec.publicValue; - break; -#endif /* NSS_ENABLE_ECC */ - } - PORT_Assert(pubKeyIndex != NULL); - - cka_id = PK11_MakeIDFromPubKey(pubKeyIndex); - pubIsToken = (PRBool)PK11_HasAttributeSet(slot,pubID, CKA_TOKEN); - - PK11_SETATTRS(&setTemplate, CKA_ID, cka_id->data, cka_id->len); - - if (haslock) { PK11_EnterSlotMonitor(slot); } - crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, privID, - &setTemplate, 1); - - if (crv == CKR_OK && pubIsToken) { - crv = PK11_GETTAB(slot)->C_SetAttributeValue(session_handle, pubID, - &setTemplate, 1); + attrFlags |= PK11_ATTR_SESSION; } - - - if (restore) { - PK11_RestoreROSession(slot,session_handle); + if (sensitive) { + attrFlags |= (PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE); } else { - PK11_ExitSlotMonitor(slot); + attrFlags |= (PK11_ATTR_INSENSITIVE | PK11_ATTR_PUBLIC); } - SECITEM_FreeItem(cka_id,PR_TRUE); - - - if (crv != CKR_OK) { - PK11_DestroyObject(slot,pubID); - PK11_DestroyObject(slot,privID); - PORT_SetError( PK11_MapError(crv) ); - *pubKey = NULL; - return NULL; - } - - privKey = PK11_MakePrivKey(slot,keyType,(PRBool)!token,privID,wincx); - if (privKey == NULL) { - SECKEY_DestroyPublicKey(*pubKey); - PK11_DestroyObject(slot,privID); - *pubKey = NULL; - return NULL; /* due to pairwise consistency check */ - } - - /* Perform PKCS #11 pairwise consistency check. */ - rv = pk11_PairwiseConsistencyCheck( *pubKey, privKey, &test_mech, wincx ); - if( rv != SECSuccess ) { - SECKEY_DestroyPublicKey( *pubKey ); - SECKEY_DestroyPrivateKey( privKey ); - *pubKey = NULL; - privKey = NULL; - return NULL; - } - - return privKey; + return PK11_GenerateKeyPairWithFlags(slot, type, param, pubKey, + attrFlags, wincx); } /* build a public KEA key from the public value */ @@ -1941,9 +1162,7 @@ PK11_ImportEncryptedPrivateKeyInfo(PK11SlotInfo *slot, CKA_UNWRAP, CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER }; CK_ATTRIBUTE_TYPE dsaUsage[] = { CKA_SIGN }; CK_ATTRIBUTE_TYPE dhUsage[] = { CKA_DERIVE }; -#ifdef NSS_ENABLE_ECC CK_ATTRIBUTE_TYPE ecUsage[] = { CKA_SIGN, CKA_DERIVE }; -#endif /* NSS_ENABLE_ECC */ if((epki == NULL) || (pwitem == NULL)) return SECFailure; @@ -1982,7 +1201,6 @@ PK11_ImportEncryptedPrivateKeyInfo(PK11SlotInfo *slot, usage = dsaUsage; usageCount = sizeof(dsaUsage)/sizeof(dsaUsage[0]); break; -#ifdef NSS_ENABLE_ECC case ecKey: key_type = CKK_EC; switch (keyUsage & (KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT)) { @@ -2001,7 +1219,6 @@ PK11_ImportEncryptedPrivateKeyInfo(PK11SlotInfo *slot, break; } break; -#endif /* NSS_ENABLE_ECC */ } try_faulty_3des: @@ -2102,7 +1319,6 @@ pk11_private_key_encrypt_buffer_length(SECKEYPrivateKey *key) { CK_ATTRIBUTE rsaTemplate = { CKA_MODULUS, NULL, 0 }; CK_ATTRIBUTE dsaTemplate = { CKA_PRIME, NULL, 0 }; -#ifdef NSS_ENABLE_ECC /* XXX We should normally choose an attribute such that * factor times its size is enough to hold the private key. * For EC keys, we have no choice but to use CKA_EC_PARAMS, @@ -2111,7 +1327,6 @@ pk11_private_key_encrypt_buffer_length(SECKEYPrivateKey *key) * is quite small so we bump up factor from 10 to 15. */ CK_ATTRIBUTE ecTemplate = { CKA_EC_PARAMS, NULL, 0 }; -#endif /* NSS_ENABLE_ECC */ CK_ATTRIBUTE_PTR pTemplate; CK_RV crv; int length; @@ -2129,12 +1344,10 @@ pk11_private_key_encrypt_buffer_length(SECKEYPrivateKey *key) case dhKey: pTemplate = &dsaTemplate; break; -#ifdef NSS_ENABLE_ECC case ecKey: pTemplate = &ecTemplate; factor = 15; break; -#endif /* NSS_ENABLE_ECC */ case fortezzaKey: default: pTemplate = NULL; @@ -2447,6 +1660,46 @@ loser: } SECKEYPrivateKey* +PK11_CopyTokenPrivKeyToSessionPrivKey(PK11SlotInfo *destSlot, + SECKEYPrivateKey *privKey) +{ + CK_RV crv; + CK_OBJECT_HANDLE newKeyID; + + static const CK_BBOOL ckfalse = CK_FALSE; + static const CK_ATTRIBUTE template[1] = { + { CKA_TOKEN, (CK_BBOOL *)&ckfalse, sizeof ckfalse } + }; + + if (destSlot && destSlot != privKey->pkcs11Slot) { + SECKEYPrivateKey *newKey = + pk11_loadPrivKey(destSlot, + privKey, + NULL, /* pubKey */ + PR_FALSE, /* token */ + PR_FALSE);/* sensitive */ + if (newKey) + return newKey; + } + destSlot = privKey->pkcs11Slot; + PK11_Authenticate(destSlot, PR_TRUE, privKey->wincx); + PK11_EnterSlotMonitor(destSlot); + crv = PK11_GETTAB(destSlot)->C_CopyObject( destSlot->session, + privKey->pkcs11ID, + (CK_ATTRIBUTE *)template, + 1, &newKeyID); + PK11_ExitSlotMonitor(destSlot); + + if (crv != CKR_OK) { + PORT_SetError( PK11_MapError(crv) ); + return NULL; + } + + return PK11_MakePrivKey(destSlot, privKey->keyType, PR_TRUE /*isTemp*/, + newKeyID, privKey->wincx); +} + +SECKEYPrivateKey* PK11_ConvertSessionPrivKeyToTokenPrivKey(SECKEYPrivateKey *privk, void* wincx) { PK11SlotInfo* slot = privk->pkcs11Slot; @@ -2461,6 +1714,10 @@ PK11_ConvertSessionPrivKeyToTokenPrivKey(SECKEYPrivateKey *privk, void* wincx) PK11_Authenticate(slot, PR_TRUE, wincx); rwsession = PK11_GetRWSession(slot); + if (rwsession == CK_INVALID_SESSION) { + PORT_SetError(SEC_ERROR_BAD_DATA); + return NULL; + } crv = PK11_GETTAB(slot)->C_CopyObject(rwsession, privk->pkcs11ID, template, 1, &newKeyID); PK11_RestoreROSession(slot, rwsession); @@ -2473,6 +1730,7 @@ PK11_ConvertSessionPrivKeyToTokenPrivKey(SECKEYPrivateKey *privk, void* wincx) return PK11_MakePrivKey(slot, nullKey /*KeyType*/, PR_FALSE /*isTemp*/, newKeyID, NULL /*wincx*/); } + /* * destroy a private key if there are no matching certs. * this function also frees the privKey structure. diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c index aa8ad695f..08c0af2db 100644 --- a/security/nss/lib/pk11wrap/pk11cert.c +++ b/security/nss/lib/pk11wrap/pk11cert.c @@ -191,11 +191,9 @@ PK11_IsUserCert(PK11SlotInfo *slot, CERTCertificate *cert, pubKey->u.dh.publicValue.len); break; case ecKey: -#ifdef NSS_ENABLE_ECC PK11_SETATTRS(&theTemplate,CKA_EC_POINT, pubKey->u.ec.publicValue.data, pubKey->u.ec.publicValue.len); -#endif /* NSS_ENABLE_ECC */ break; case keaKey: case fortezzaKey: @@ -432,12 +430,8 @@ PK11_DeleteTokenCertAndKey(CERTCertificate *cert,void *wincx) pubKey = pk11_FindPubKeyByAnyCert(cert, &slot, wincx); if (privKey) { -#ifdef NSS_CLASSIC - PK11_DestroyTokenObject(cert->slot,cert->pkcs11ID); -#else /* For 3.4, utilize the generic cert delete function */ SEC_DeletePermCertificate(cert); -#endif PK11_DeleteTokenPrivateKey(privKey, PR_FALSE); } if ((pubKey != CK_INVALID_HANDLE) && (slot != NULL)) { @@ -457,39 +451,6 @@ typedef struct pk11DoCertCallbackStr { void *callbackArg; } pk11DoCertCallback; -#ifdef NSS_CLASSIC -/* - * callback to map object handles to certificate structures. - */ -static SECStatus -pk11_DoCerts(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID, void *arg) -{ - CERTCertificate *cert; - pk11DoCertCallback *certcb = (pk11DoCertCallback *) arg; - - cert = PK11_MakeCertFromHandle(slot, certID, NULL); - - if (cert == NULL) { - return SECFailure; - } - - if (certcb ) { - if (certcb->callback) { - (*certcb->callback)(slot, cert, certcb->callbackArg); - } - if (certcb->noslotcallback) { - (*certcb->noslotcallback)(cert, certcb->callbackArg); - } - if (certcb->itemcallback) { - (*certcb->itemcallback)(cert, NULL, certcb->callbackArg); - } - } - - CERT_DestroyCertificate(cert); - - return SECSuccess; -} -#endif typedef struct pk11CertCallbackStr { SECStatus(* callback)(CERTCertificate*,SECItem *,void *); @@ -513,26 +474,8 @@ static SECStatus fake_der_cb(CERTCertificate *c, void *a) */ SECStatus PK11_TraverseSlotCerts(SECStatus(* callback)(CERTCertificate*,SECItem *,void *), - void *arg, void *wincx) { -#ifdef NSS_CLASSIC - pk11DoCertCallback caller; - pk11TraverseSlot creater; - CK_ATTRIBUTE theTemplate; - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - - PK11_SETATTRS(&theTemplate, CKA_CLASS, &certClass, sizeof(certClass)); - - caller.callback = NULL; - caller.noslotcallback = NULL; - caller.itemcallback = callback; - caller.callbackArg = arg; - creater.callback = pk11_DoCerts; - creater.callbackArg = (void *) & caller; - creater.findTemplate = &theTemplate; - creater.templateCount = 1; - - return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, wincx); -#else + void *arg, void *wincx) +{ NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain(); struct fake_der_cb_argstr fda; struct nss3_cert_cbstr pk11cb; @@ -546,7 +489,6 @@ PK11_TraverseSlotCerts(SECStatus(* callback)(CERTCertificate*,SECItem *,void *), pk11cb.arg = &fda; NSSTrustDomain_TraverseCertificates(defaultTD, convert_cert, &pk11cb); return SECSuccess; -#endif } static void @@ -584,19 +526,6 @@ transfer_token_certs_to_collection(nssList *certList, NSSToken *token, CERTCertificate * PK11_FindCertFromNickname(char *nickname, void *wincx) { -#ifdef NSS_CLASSIC - PK11SlotInfo *slot; - int count=0; - CK_OBJECT_HANDLE *certID = PK11_FindObjectsFromNickname(nickname,&slot, - CKO_CERTIFICATE, &count, wincx); - CERTCertificate *cert; - - if (certID == CK_INVALID_HANDLE) return NULL; - cert = PK11_MakeCertFromHandle(slot,certID[0],NULL); - PK11_FreeSlot(slot); - PORT_Free(certID); - return cert; -#else PRStatus status; CERTCertificate *rvCert = NULL; NSSCertificate *cert = NULL; @@ -703,36 +632,11 @@ loser: } if (nickCopy) PORT_Free(nickCopy); return NULL; -#endif } CERTCertList * -PK11_FindCertsFromNickname(char *nickname, void *wincx) { -#ifdef NSS_CLASSIC - PK11SlotInfo *slot; - int i,count = 0; - CK_OBJECT_HANDLE *certID = PK11_FindObjectsFromNickname(nickname,&slot, - CKO_CERTIFICATE, &count, wincx); - CERTCertList *certList = NULL; - - if (certID == NULL) return NULL; - - certList= CERT_NewCertList(); - - for (i=0; i < count; i++) { - CERTCertificate *cert = PK11_MakeCertFromHandle(slot,certID[i],NULL); - - if (cert) CERT_AddCertToListTail(certList,cert); - } - - if (CERT_LIST_HEAD(certList) == NULL) { - CERT_DestroyCertList(certList); - certList = NULL; - } - PK11_FreeSlot(slot); - PORT_Free(certID); - return certList; -#else +PK11_FindCertsFromNickname(char *nickname, void *wincx) +{ char *nickCopy; char *delimit = NULL; char *tokenName; @@ -827,7 +731,6 @@ PK11_FindCertsFromNickname(char *nickname, void *wincx) { nss_ZFreeIf(foundCerts); } return certList; -#endif } /* @@ -854,9 +757,7 @@ PK11_GetPubIndexKeyID(CERTCertificate *cert) { newItem = SECITEM_DupItem(&pubk->u.dh.publicValue); break; case ecKey: -#ifdef NSS_ENABLE_ECC newItem = SECITEM_DupItem(&pubk->u.ec.publicValue); -#endif /* NSS_ENABLE_ECC */ break; case fortezzaKey: default: @@ -889,154 +790,6 @@ SECStatus PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert, CK_OBJECT_HANDLE key, char *nickname, PRBool includeTrust) { -#ifdef NSS_CLASSIC - int len = 0; - SECItem *keyID = pk11_mkcertKeyID(cert); - CK_ATTRIBUTE keyAttrs[] = { - { CKA_LABEL, NULL, 0}, - { CKA_SUBJECT, NULL, 0}, - }; - CK_OBJECT_CLASS certc = CKO_CERTIFICATE; - CK_CERTIFICATE_TYPE certType = CKC_X_509; - CK_OBJECT_HANDLE certID; - CK_SESSION_HANDLE rwsession; - CK_BBOOL cktrue = CK_TRUE; - SECStatus rv = SECFailure; - CK_ATTRIBUTE certAttrs[] = { - { CKA_ID, NULL, 0 }, - { CKA_LABEL, NULL, 0}, - { CKA_CLASS, NULL, 0}, - { CKA_TOKEN, NULL, 0}, - { CKA_CERTIFICATE_TYPE, NULL, 0}, - { CKA_SUBJECT, NULL, 0}, - { CKA_ISSUER, NULL, 0}, - { CKA_SERIAL_NUMBER, NULL, 0}, - { CKA_VALUE, NULL, 0}, - { CKA_NETSCAPE_TRUST, NULL, 0}, - { CKA_NETSCAPE_EMAIL, NULL, 0}, - }; - int certCount = sizeof(certAttrs)/sizeof(certAttrs[0]), keyCount = 2; - int realCount = 0; - CK_ATTRIBUTE *attrs; - CK_RV crv; - SECCertUsage *certUsage = NULL; - SECItem derSerial = { 0 }; - NSSToken *token; - - if (keyID == NULL) { - PORT_SetError(SEC_ERROR_ADDING_CERT); - return rv; - } - - len = ((nickname) ? PORT_Strlen(nickname) : 0); - - attrs = certAttrs; - PK11_SETATTRS(attrs,CKA_ID, keyID->data, keyID->len); attrs++; - if (nickname) { - PK11_SETATTRS(attrs,CKA_LABEL, nickname, len ); attrs++; - } - PK11_SETATTRS(attrs,CKA_CLASS, &certc, sizeof(certc) ); attrs++; - PK11_SETATTRS(attrs,CKA_TOKEN, &cktrue, sizeof(cktrue) ); attrs++; - PK11_SETATTRS(attrs,CKA_CERTIFICATE_TYPE, &certType, - sizeof(certType)); attrs++; - PK11_SETATTRS(attrs,CKA_SUBJECT, cert->derSubject.data, - cert->derSubject.len ); attrs++; - PK11_SETATTRS(attrs,CKA_ISSUER, cert->derIssuer.data, - cert->derIssuer.len ); attrs++; - if (PR_TRUE) { - /* CERTCertificate stores serial numbers decoded. I need the DER - * here. sigh. - */ - CERT_SerialNumberFromDERCert(&cert->derCert, &derSerial); - PK11_SETATTRS(attrs,CKA_SERIAL_NUMBER, derSerial.data, derSerial.len); - attrs++; - } - PK11_SETATTRS(attrs,CKA_VALUE, cert->derCert.data, - cert->derCert.len); attrs++; - if (includeTrust && PK11_IsInternal(slot)) { - certUsage = (SECCertUsage*)PORT_Alloc(sizeof(SECCertUsage)); - if(!certUsage) { - SECITEM_FreeItem(keyID,PR_TRUE); - PORT_SetError(SEC_ERROR_NO_MEMORY); - return rv; - } - *certUsage = certUsageUserCertImport; - PK11_SETATTRS(attrs,CKA_NETSCAPE_TRUST, certUsage, - sizeof(SECCertUsage)); - attrs++; - if (cert->emailAddr && cert->emailAddr[0]) { - PK11_SETATTRS(attrs,CKA_NETSCAPE_EMAIL, cert->emailAddr, - PORT_Strlen(cert->emailAddr); - attrs++; - } - } - realCount = attrs - certAttrs; - PORT_Assert(realCount <= certCount); - - attrs = keyAttrs; - if(nickname) { - PK11_SETATTRS(attrs,CKA_LABEL, nickname, len ); attrs++; - } - PK11_SETATTRS(attrs,CKA_SUBJECT, cert->derSubject.data, - cert->derSubject.len ); - - if(!nickname) { - certCount--; - keyCount--; - } - - rwsession = PK11_GetRWSession(slot); - if (key != CK_INVALID_HANDLE) { - crv = PK11_GETTAB(slot)->C_SetAttributeValue(rwsession,key,keyAttrs, - keyCount); - if (crv != CKR_OK) { - PORT_SetError( PK11_MapError(crv) ); - goto done; - } - } - - crv = PK11_GETTAB(slot)-> - C_CreateObject(rwsession,certAttrs,realCount,&certID); - if (crv == CKR_OK) { - rv = SECSuccess; - } else { - PORT_SetError( PK11_MapError(crv) ); - } - - if (!cert->nickname && nickname) { - cert->nickname = PORT_ArenaStrdup(cert->arena, nickname); - } - - cert->pkcs11ID = certID; - cert->dbhandle = STAN_GetDefaultTrustDomain(); - if (cert->slot == NULL) { - cert->slot = PK11_ReferenceSlot(slot); - cert->series = slot->series; - cert->ownSlot = PR_TRUE; - if (cert->nssCertificate) { - nssCryptokiInstance *instance; - NSSCertificate *c = cert->nssCertificate; - instance = nss_ZNEW(c->object.arena, nssCryptokiInstance); - instance->token = slot->nssToken; - instance->handle = cert->pkcs11ID; - instance->isTokenObject = PR_TRUE; - nssPKIObject_AddInstance(&c->object, instance); - } else { - cert->nssCertificate = STAN_GetNSSCertificate(cert); - } - } - cert->trust = nssTrust_GetCERTCertTrustForCert(cert->nssCertificate, cert); - token = PK11Slot_GetNSSToken(slot); - -done: - if (derSerial.data) PORT_Free(derSerial.data); - SECITEM_FreeItem(keyID,PR_TRUE); - PK11_RestoreROSession(slot,rwsession); - if(certUsage) { - PORT_Free(certUsage); - } - return rv; -#else PRStatus status; NSSCertificate *c; nssCryptokiObject *keyobj, *certobj; @@ -1126,7 +879,6 @@ loser: SECITEM_FreeItem(keyID,PR_TRUE); PORT_SetError(SEC_ERROR_ADDING_CERT); return SECFailure; -#endif } SECStatus @@ -1704,36 +1456,6 @@ CERTCertificate * PK11_FindCertByIssuerAndSN(PK11SlotInfo **slotPtr, CERTIssuerAndSN *issuerSN, void *wincx) { -#ifdef NSS_CLASSIC - CK_OBJECT_HANDLE certHandle; - CERTCertificate *cert = NULL; - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - CK_ATTRIBUTE searchTemplate[] = { - { CKA_CLASS, NULL, 0 }, - { CKA_ISSUER, NULL, 0 }, - { CKA_SERIAL_NUMBER, NULL, 0} - }; - int count = sizeof(searchTemplate)/sizeof(CK_ATTRIBUTE); - CK_ATTRIBUTE *attrs = searchTemplate; - - PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass)); attrs++; - PK11_SETATTRS(attrs, CKA_ISSUER, issuerSN->derIssuer.data, - issuerSN->derIssuer.len); attrs++; - PK11_SETATTRS(attrs, CKA_SERIAL_NUMBER, issuerSN->serialNumber.data, - issuerSN->serialNumber.len); - - certHandle = pk11_FindCertObjectByTemplate - (slotPtr,searchTemplate,count,wincx); - if (certHandle == CK_INVALID_HANDLE) { - return NULL; - } - cert = PK11_MakeCertFromHandle(*slotPtr,certHandle,NULL); - if (cert == NULL) { - PK11_FreeSlot(*slotPtr); - return NULL; - } - return cert; -#else CERTCertificate *rvCert = NULL; NSSCertificate *cert; NSSDER issuer, serial; @@ -1792,7 +1514,6 @@ PK11_FindCertByIssuerAndSN(PK11SlotInfo **slotPtr, CERTIssuerAndSN *issuerSN, SECITEM_FreeItem(derSerial, PR_TRUE); return rvCert; -#endif } CK_OBJECT_HANDLE @@ -1940,34 +1661,6 @@ SECStatus PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert, PK11SlotInfo *slot, SECStatus(* callback)(CERTCertificate*, void *), void *arg) { -#ifdef NSS_CLASSIC - pk11DoCertCallback caller; - pk11TraverseSlot callarg; - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - CK_ATTRIBUTE theTemplate[] = { - { CKA_CLASS, NULL, 0 }, - { CKA_SUBJECT, NULL, 0 }, - }; - CK_ATTRIBUTE *attr = theTemplate; - int templateSize = sizeof(theTemplate)/sizeof(theTemplate[0]); - - PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++; - PK11_SETATTRS(attr,CKA_SUBJECT,cert->derSubject.data,cert->derSubject.len); - - if (slot == NULL) { - return SECSuccess; - } - caller.noslotcallback = callback; - caller.callback = NULL; - caller.itemcallback = NULL; - caller.callbackArg = arg; - callarg.callback = pk11_DoCerts; - callarg.callbackArg = (void *) & caller; - callarg.findTemplate = theTemplate; - callarg.templateCount = templateSize; - - return PK11_TraverseSlot(slot, &callarg); -#else PRStatus nssrv = PR_SUCCESS; NSSToken *token; NSSDER subject; @@ -2020,46 +1713,12 @@ PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert, PK11SlotInfo *slot, nssCertificateArray_Destroy(certs); } return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; -#endif } SECStatus PK11_TraverseCertsForNicknameInSlot(SECItem *nickname, PK11SlotInfo *slot, SECStatus(* callback)(CERTCertificate*, void *), void *arg) { -#ifdef NSS_CLASSIC - pk11DoCertCallback caller; - pk11TraverseSlot callarg; - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - CK_ATTRIBUTE theTemplate[] = { - { CKA_CLASS, NULL, 0 }, - { CKA_LABEL, NULL, 0 }, - }; - CK_ATTRIBUTE *attr = theTemplate; - int templateSize = sizeof(theTemplate)/sizeof(theTemplate[0]); - - if(!nickname) { - return SECSuccess; - } - - PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++; - PK11_SETATTRS(attr,CKA_LABEL,nickname->data,nickname->len); - - if (slot == NULL) { - return SECSuccess; - } - - caller.noslotcallback = callback; - caller.callback = NULL; - caller.itemcallback = NULL; - caller.callbackArg = arg; - callarg.callback = pk11_DoCerts; - callarg.callbackArg = (void *) & caller; - callarg.findTemplate = theTemplate; - callarg.templateCount = templateSize; - - return PK11_TraverseSlot(slot, &callarg); -#else struct nss3_cert_cbstr pk11cb; PRStatus nssrv = PR_SUCCESS; NSSToken *token; @@ -2132,39 +1791,12 @@ loser: nssList_Destroy(nameList); } return SECFailure; -#endif } SECStatus PK11_TraverseCertsInSlot(PK11SlotInfo *slot, SECStatus(* callback)(CERTCertificate*, void *), void *arg) { -#ifdef NSS_CLASSIC - pk11DoCertCallback caller; - pk11TraverseSlot callarg; - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - CK_ATTRIBUTE theTemplate[] = { - { CKA_CLASS, NULL, 0 }, - }; - CK_ATTRIBUTE *attr = theTemplate; - int templateSize = sizeof(theTemplate)/sizeof(theTemplate[0]); - - PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++; - - if (slot == NULL) { - return SECSuccess; - } - - caller.noslotcallback = callback; - caller.callback = NULL; - caller.itemcallback = NULL; - caller.callbackArg = arg; - callarg.callback = pk11_DoCerts; - callarg.callbackArg = (void *) & caller; - callarg.findTemplate = theTemplate; - callarg.templateCount = templateSize; - return PK11_TraverseSlot(slot, &callarg); -#else PRStatus nssrv; NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); NSSToken *tok; @@ -2212,7 +1844,6 @@ PK11_TraverseCertsInSlot(PK11SlotInfo *slot, nssCertificateArray_Destroy(certs); } return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure; -#endif } /* @@ -2645,22 +2276,6 @@ pk11ListCertCallback(NSSCertificate *c, void *arg) CERTCertList * PK11_ListCerts(PK11CertListType type, void *pwarg) { -#ifdef NSS_CLASSIC - CERTCertList *certList = NULL; - struct listCertsStr listCerts; - - certList= CERT_NewCertList(); - listCerts.type = type; - listCerts.certList = certList; - - PK11_TraverseSlotCerts(pk11ListCertCallback,&listCerts,pwarg); - - if (CERT_LIST_HEAD(certList) == NULL) { - CERT_DestroyCertList(certList); - certList = NULL; - } - return certList; -#else NSSTrustDomain *defaultTD = STAN_GetDefaultTrustDomain(); CERTCertList *certList = NULL; struct listCertsStr listCerts; @@ -2673,7 +2288,6 @@ PK11_ListCerts(PK11CertListType type, void *pwarg) NSSTrustDomain_TraverseCertificates(defaultTD, pk11ListCertCallback, &listCerts); return certList; -#endif } SECItem * diff --git a/security/nss/lib/pk11wrap/pk11err.c b/security/nss/lib/pk11wrap/pk11err.c index 28559d8d8..a63475636 100644 --- a/security/nss/lib/pk11wrap/pk11err.c +++ b/security/nss/lib/pk11wrap/pk11err.c @@ -95,8 +95,8 @@ PK11_MapError(CK_RV rv) { MAPERROR(CKR_OPERATION_ACTIVE, SEC_ERROR_LIBRARY_FAILURE) MAPERROR(CKR_OPERATION_NOT_INITIALIZED,SEC_ERROR_LIBRARY_FAILURE ) MAPERROR(CKR_PIN_INCORRECT, SEC_ERROR_BAD_PASSWORD) - MAPERROR(CKR_PIN_INVALID, SEC_ERROR_BAD_PASSWORD) - MAPERROR(CKR_PIN_LEN_RANGE, SEC_ERROR_BAD_PASSWORD) + MAPERROR(CKR_PIN_INVALID, SEC_ERROR_INVALID_PASSWORD) + MAPERROR(CKR_PIN_LEN_RANGE, SEC_ERROR_INVALID_PASSWORD) MAPERROR(CKR_SESSION_CLOSED, SEC_ERROR_LIBRARY_FAILURE) MAPERROR(CKR_SESSION_COUNT, SEC_ERROR_NO_MEMORY) /* XXXX? */ MAPERROR(CKR_SESSION_HANDLE_INVALID, SEC_ERROR_BAD_DATA) @@ -124,7 +124,7 @@ PK11_MapError(CK_RV rv) { MAPERROR(CKR_VENDOR_DEFINED, SEC_ERROR_LIBRARY_FAILURE) MAPERROR(CKR_NETSCAPE_CERTDB_FAILED, SEC_ERROR_BAD_DATABASE) MAPERROR(CKR_NETSCAPE_KEYDB_FAILED, SEC_ERROR_BAD_DATABASE) - + MAPERROR(CKR_CANT_LOCK, SEC_ERROR_INCOMPATIBLE_PKCS11) #ifdef PK11_ERROR_USE_ARRAY }; diff --git a/security/nss/lib/pk11wrap/pk11load.c b/security/nss/lib/pk11wrap/pk11load.c index 6017361ae..d0d305eb4 100644 --- a/security/nss/lib/pk11wrap/pk11load.c +++ b/security/nss/lib/pk11wrap/pk11load.c @@ -45,6 +45,7 @@ #include "secmodi.h" #include "secmodti.h" #include "nssilock.h" +#include "secerr.h" extern void FC_GetFunctionList(void); extern void NSC_GetFunctionList(void); @@ -90,16 +91,53 @@ static const CK_C_INITIALIZE_ARGS secmodLockFunctions = { ,NULL }; +static PRBool loadSingleThreadedModules = PR_TRUE; +static PRBool enforceAlreadyInitializedError = PR_TRUE; +static PRBool finalizeModules = PR_TRUE; + +/* set global options for NSS PKCS#11 module loader */ +SECStatus pk11_setGlobalOptions(PRBool noSingleThreadedModules, + PRBool allowAlreadyInitializedModules, + PRBool dontFinalizeModules) +{ + if (noSingleThreadedModules) { + loadSingleThreadedModules = PR_FALSE; + } else { + loadSingleThreadedModules = PR_TRUE; + } + if (allowAlreadyInitializedModules) { + enforceAlreadyInitializedError = PR_FALSE; + } else { + enforceAlreadyInitializedError = PR_TRUE; + } + if (dontFinalizeModules) { + finalizeModules = PR_FALSE; + } else { + finalizeModules = PR_TRUE; + } + return SECSuccess; +} + +PRBool pk11_getFinalizeModulesOption(void) +{ + return finalizeModules; +} + /* * collect the steps we need to initialize a module in a single function */ SECStatus -secmod_ModuleInit(SECMODModule *mod) +secmod_ModuleInit(SECMODModule *mod, PRBool* alreadyLoaded) { CK_C_INITIALIZE_ARGS moduleArgs; CK_VOID_PTR pInitArgs; CK_RV crv; + if (!mod || !alreadyLoaded) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (mod->isThreadSafe == PR_FALSE) { pInitArgs = NULL; } else if (mod->libraryParams == NULL) { @@ -110,6 +148,11 @@ secmod_ModuleInit(SECMODModule *mod) pInitArgs = &moduleArgs; } crv = PK11_GETTAB(mod)->C_Initialize(pInitArgs); + if ((CKR_CRYPTOKI_ALREADY_INITIALIZED == crv) && + (!enforceAlreadyInitializedError)) { + *alreadyLoaded = PR_TRUE; + return SECSuccess; + } if (crv != CKR_OK) { if (pInitArgs == NULL || crv == CKR_NETSCAPE_CERTDB_FAILED || @@ -117,8 +160,17 @@ secmod_ModuleInit(SECMODModule *mod) PORT_SetError(PK11_MapError(crv)); return SECFailure; } + if (!loadSingleThreadedModules) { + PORT_SetError(SEC_ERROR_INCOMPATIBLE_PKCS11); + return SECFailure; + } mod->isThreadSafe = PR_FALSE; crv = PK11_GETTAB(mod)->C_Initialize(NULL); + if ((CKR_CRYPTOKI_ALREADY_INITIALIZED == crv) && + (!enforceAlreadyInitializedError)) { + *alreadyLoaded = PR_TRUE; + return SECSuccess; + } if (crv != CKR_OK) { PORT_SetError(PK11_MapError(crv)); return SECFailure; @@ -180,6 +232,7 @@ SECMOD_LoadPKCS11Module(SECMODModule *mod) { CK_INFO info; CK_ULONG slotCount = 0; SECStatus rv; + PRBool alreadyLoaded = PR_FALSE; if (mod->loaded) return SECSuccess; @@ -266,7 +319,7 @@ SECMOD_LoadPKCS11Module(SECMODModule *mod) { mod->isThreadSafe = PR_TRUE; /* Now we initialize the module */ - rv = secmod_ModuleInit(mod); + rv = secmod_ModuleInit(mod, &alreadyLoaded); if (rv != SECSuccess) { goto fail; } @@ -275,11 +328,16 @@ SECMOD_LoadPKCS11Module(SECMODModule *mod) { if (PK11_GETTAB(mod)->C_GetInfo(&info) != CKR_OK) goto fail2; if (info.cryptokiVersion.major != 2) goto fail2; /* all 2.0 are a priori *not* thread safe */ - if (info.cryptokiVersion.minor < 1) mod->isThreadSafe = PR_FALSE; - + if (info.cryptokiVersion.minor < 1) { + if (!loadSingleThreadedModules) { + PORT_SetError(SEC_ERROR_INCOMPATIBLE_PKCS11); + goto fail2; + } else { + mod->isThreadSafe = PR_FALSE; + } + } mod->cryptokiVersion = info.cryptokiVersion; - /* If we don't have a common name, get it from the PKCS 11 module */ if ((mod->commonName == NULL) || (mod->commonName[0] == 0)) { mod->commonName = PK11_MakeString(mod->arena,NULL, @@ -325,7 +383,9 @@ SECMOD_LoadPKCS11Module(SECMODModule *mod) { mod->moduleID = nextModuleID++; return SECSuccess; fail2: - PK11_GETTAB(mod)->C_Finalize(NULL); + if (enforceAlreadyInitializedError || (!alreadyLoaded)) { + PK11_GETTAB(mod)->C_Finalize(NULL); + } fail: mod->functionList = NULL; if (library) PR_UnloadLibrary(library); @@ -339,8 +399,9 @@ SECMOD_UnloadModule(SECMODModule *mod) { if (!mod->loaded) { return SECFailure; } - - if (!mod->moduleDBOnly) PK11_GETTAB(mod)->C_Finalize(NULL); + if (finalizeModules) { + if (!mod->moduleDBOnly) PK11_GETTAB(mod)->C_Finalize(NULL); + } mod->moduleID = 0; mod->loaded = PR_FALSE; diff --git a/security/nss/lib/pk11wrap/pk11mech.c b/security/nss/lib/pk11wrap/pk11mech.c index 2b73ed3ba..1f8f2a372 100644 --- a/security/nss/lib/pk11wrap/pk11mech.c +++ b/security/nss/lib/pk11wrap/pk11mech.c @@ -353,6 +353,7 @@ PK11_GetKeyType(CK_MECHANISM_TYPE type,unsigned long len) case CKM_SHA512_RSA_PKCS: case CKM_KEY_WRAP_SET_OAEP: case CKM_RSA_PKCS_KEY_PAIR_GEN: + case CKM_RSA_X9_31_KEY_PAIR_GEN: return CKK_RSA; case CKM_DSA: case CKM_DSA_SHA1: @@ -526,6 +527,8 @@ PK11_GetKeyGenWithSize(CK_MECHANISM_TYPE type, int size) case CKM_KEY_WRAP_SET_OAEP: case CKM_RSA_PKCS_KEY_PAIR_GEN: return CKM_RSA_PKCS_KEY_PAIR_GEN; + case CKM_RSA_X9_31_KEY_PAIR_GEN: + return CKM_RSA_X9_31_KEY_PAIR_GEN; case CKM_DSA: case CKM_DSA_SHA1: case CKM_DSA_KEY_PAIR_GEN: @@ -1738,7 +1741,7 @@ have_key_len: /* Make a Key type to an appropriate signing/verification mechanism */ CK_MECHANISM_TYPE -pk11_mapSignKeyType(KeyType keyType) +PK11_MapSignKeyType(KeyType keyType) { switch (keyType) { case rsaKey: @@ -1746,10 +1749,8 @@ pk11_mapSignKeyType(KeyType keyType) case fortezzaKey: case dsaKey: return CKM_DSA; -#ifdef NSS_ENABLE_ECC case ecKey: return CKM_ECDSA; -#endif /* NSS_ENABLE_ECC */ case dhKey: default: break; diff --git a/security/nss/lib/pk11wrap/pk11nobj.c b/security/nss/lib/pk11wrap/pk11nobj.c index 523e0dafe..db9aa6ba9 100644 --- a/security/nss/lib/pk11wrap/pk11nobj.c +++ b/security/nss/lib/pk11wrap/pk11nobj.c @@ -431,88 +431,6 @@ SECItem * PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *crlHandle, SECItem *name, int type, char **url) { -#ifdef NSS_CLASSIC - CK_OBJECT_CLASS crlClass = CKO_NETSCAPE_CRL; - CK_ATTRIBUTE theTemplate[] = { - { CKA_SUBJECT, NULL, 0 }, - { CKA_CLASS, NULL, 0 }, - { CKA_NETSCAPE_KRL, NULL, 0 }, - }; - CK_ATTRIBUTE crlData[] = { - { CKA_VALUE, NULL, 0 }, - { CKA_NETSCAPE_URL, NULL, 0 }, - }; - /* if you change the array, change the variable below as well */ - int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); - CK_BBOOL ck_true = CK_TRUE; - CK_BBOOL ck_false = CK_FALSE; - CK_OBJECT_HANDLE crlh = CK_INVALID_HANDLE; - CK_ATTRIBUTE *attrs = theTemplate; - CK_RV crv; - SECItem *derCrl = NULL; - - PK11_SETATTRS(attrs, CKA_SUBJECT, name->data, name->len); attrs++; - PK11_SETATTRS(attrs, CKA_CLASS, &crlClass, sizeof(crlClass)); attrs++; - PK11_SETATTRS(attrs, CKA_NETSCAPE_KRL, (type == SEC_CRL_TYPE) ? - &ck_false : &ck_true, sizeof (CK_BBOOL)); attrs++; - - if (*slot) { - crlh = pk11_FindObjectByTemplate(*slot,theTemplate,tsize); - } else { - PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, - PR_FALSE,PR_TRUE,NULL); - PK11SlotListElement *le; - - /* loop through all the fortezza tokens */ - for (le = list->head; le; le = le->next) { - crlh = pk11_FindObjectByTemplate(le->slot,theTemplate,tsize); - if (crlh != CK_INVALID_HANDLE) { - *slot = PK11_ReferenceSlot(le->slot); - break; - } - } - PK11_FreeSlotList(list); - } - - if (crlh == CK_INVALID_HANDLE) { - PORT_SetError(SEC_ERROR_NO_KRL); - return NULL; - } - crv = PK11_GetAttributes(NULL,*slot,crlh,crlData,2); - if (crv != CKR_OK) { - PORT_SetError(PK11_MapError (crv)); - goto loser; - } - - derCrl = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if (derCrl == NULL) { - goto loser; - } - - /* why are we arbitrarily picking the first CRL ??? */ - derCrl->data = crlData[0].pValue; - derCrl->len = crlData[0].ulValueLen; - - if (crlHandle) { - *crlHandle = crlh; - } - - if ((url) && crlData[1].ulValueLen != 0) { - /* make sure it's a null terminated string */ - *url = PORT_ZAlloc (crlData[1].ulValueLen+1); - if (*url) { - PORT_Memcpy(*url,crlData[1].pValue,crlData[1].ulValueLen); - } - } - - -loser: - if (!derCrl) { - if (crlData[0].pValue) PORT_Free(crlData[0].pValue); - } - if (crlData[1].pValue) PORT_Free(crlData[1].pValue); - return derCrl; -#else NSSCRL **crls, **crlp, *crl; NSSDER subject; SECItem *rvItem; @@ -581,61 +499,12 @@ loser: *crlHandle = crl->object.instances[0]->handle; nssCRL_Destroy(crl); return rvItem; -#endif } CK_OBJECT_HANDLE PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, SECItem *name, char *url, int type) { -#ifdef NSS_CLASSIC - CK_OBJECT_CLASS crlClass = CKO_NETSCAPE_CRL; - CK_ATTRIBUTE theTemplate[] = { - { CKA_SUBJECT, NULL, 0 }, - { CKA_CLASS, NULL, 0 }, - { CKA_NETSCAPE_KRL, NULL, 0 }, - { CKA_NETSCAPE_URL, NULL, 0 }, - { CKA_VALUE, NULL, 0 }, - { CKA_TOKEN, NULL, 0 } - }; - /* if you change the array, change the variable below as well */ - int tsize; - CK_BBOOL ck_true = CK_TRUE; - CK_BBOOL ck_false = CK_FALSE; - CK_OBJECT_HANDLE crlh = CK_INVALID_HANDLE; - CK_ATTRIBUTE *attrs = theTemplate; - CK_SESSION_HANDLE rwsession; - CK_RV crv; - - PK11_SETATTRS(attrs, CKA_SUBJECT, name->data, name->len); attrs++; - PK11_SETATTRS(attrs, CKA_CLASS, &crlClass, sizeof(crlClass)); attrs++; - PK11_SETATTRS(attrs, CKA_NETSCAPE_KRL, (type == SEC_CRL_TYPE) ? - &ck_false : &ck_true, sizeof (CK_BBOOL)); attrs++; - if (url) { - PK11_SETATTRS(attrs, CKA_NETSCAPE_URL, url, PORT_Strlen(url)+1); attrs++; - } - PK11_SETATTRS(attrs, CKA_VALUE,crl->data,crl->len); attrs++; - PK11_SETATTRS(attrs, CKA_TOKEN, &ck_true,sizeof(CK_BBOOL)); attrs++; - - tsize = attrs - &theTemplate[0]; - PORT_Assert(tsize <= sizeof(theTemplate)/sizeof(theTemplate[0])); - - rwsession = PK11_GetRWSession(slot); - if (rwsession == CK_INVALID_SESSION) { - PORT_SetError(SEC_ERROR_READ_ONLY); - return crlh; - } - - crv = PK11_GETTAB(slot)-> - C_CreateObject(rwsession,theTemplate,tsize,&crlh); - if (crv != CKR_OK) { - PORT_SetError( PK11_MapError(crv) ); - } - - PK11_RestoreROSession(slot,rwsession); - - return crlh; -#else NSSItem derCRL, derSubject; NSSToken *token = PK11Slot_GetNSSToken(slot); nssCryptokiObject *object; @@ -655,7 +524,6 @@ PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, SECItem *name, rvH = CK_INVALID_HANDLE; } return rvH; -#endif } @@ -665,25 +533,6 @@ PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, SECItem *name, SECStatus SEC_DeletePermCRL(CERTSignedCrl *crl) { -#ifdef NSS_CLASSIC - PK11SlotInfo *slot = crl->slot; - CK_RV crv; - - if (slot == NULL) { - /* shouldn't happen */ - PORT_SetError( SEC_ERROR_CRL_INVALID); - return SECFailure; - } - - crv = PK11_DestroyTokenObject(slot,crl->pkcs11ID); - if (crv != CKR_OK) { - PORT_SetError( PK11_MapError(crv) ); - return SECFailure; - } - crl->slot = NULL; - PK11_FreeSlot(slot); - return SECSuccess; -#else PRStatus status; NSSToken *token; nssCryptokiObject *object; @@ -706,7 +555,6 @@ SEC_DeletePermCRL(CERTSignedCrl *crl) nssCryptokiObject_Destroy(object); return (status == PR_SUCCESS) ? SECSuccess : SECFailure; -#endif } /* diff --git a/security/nss/lib/pk11wrap/pk11obj.c b/security/nss/lib/pk11wrap/pk11obj.c index 0af025539..65b47ef96 100644 --- a/security/nss/lib/pk11wrap/pk11obj.c +++ b/security/nss/lib/pk11wrap/pk11obj.c @@ -97,6 +97,10 @@ PK11_DestroyTokenObject(PK11SlotInfo *slot,CK_OBJECT_HANDLE object) { rwsession = PK11_GetRWSession(slot); + if (rwsession == CK_INVALID_SESSION) { + PORT_SetError(SEC_ERROR_BAD_DATA); + return SECFailure; + } crv = PK11_GETTAB(slot)->C_DestroyObject(rwsession,object); if (crv != CKR_OK) { @@ -210,6 +214,9 @@ PK11_GetAttributes(PRArenaPool *arena,PK11SlotInfo *slot, /* make pedantic happy... note that it's only used arena != NULL */ void *mark = NULL; CK_RV crv; + PORT_Assert(slot->session != CK_INVALID_SESSION); + if (slot->session == CK_INVALID_SESSION) + return CKR_SESSION_HANDLE_INVALID; /* * first get all the lengths of the parameters. @@ -319,6 +326,10 @@ PK11_SetObjectNickname(PK11SlotInfo *slot, CK_OBJECT_HANDLE id, PK11_SETATTRS(&setTemplate, CKA_LABEL, (CK_CHAR *) nickname, len); rwsession = PK11_GetRWSession(slot); + if (rwsession == CK_INVALID_SESSION) { + PORT_SetError(SEC_ERROR_BAD_DATA); + return SECFailure; + } crv = PK11_GETTAB(slot)->C_SetAttributeValue(rwsession, id, &setTemplate, 1); PK11_RestoreROSession(slot, rwsession); @@ -389,7 +400,12 @@ PK11_CreateNewObject(PK11SlotInfo *slot, CK_SESSION_HANDLE session, rwsession = PK11_GetRWSession(slot); } else if (rwsession == CK_INVALID_SESSION) { rwsession = slot->session; - PK11_EnterSlotMonitor(slot); + if (rwsession != CK_INVALID_SESSION) + PK11_EnterSlotMonitor(slot); + } + if (rwsession == CK_INVALID_SESSION) { + PORT_SetError(SEC_ERROR_BAD_DATA); + return SECFailure; } crv = PK11_GETTAB(slot)->C_CreateObject(rwsession, theTemplate, count,objectID); @@ -407,6 +423,7 @@ PK11_CreateNewObject(PK11SlotInfo *slot, CK_SESSION_HANDLE session, } +/* This function may add a maximum of 9 attributes. */ unsigned int pk11_OpFlagsToAttributes(CK_FLAGS flags, CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue) { @@ -428,6 +445,7 @@ pk11_OpFlagsToAttributes(CK_FLAGS flags, CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue) for (; flags && test <= CKF_DERIVE; test <<= 1, ++pType) { if (test & flags) { flags ^= test; + PR_ASSERT(*pType); PK11_SETATTRS(attr, *pType, ckTrue, sizeof *ckTrue); ++attr; } @@ -498,7 +516,7 @@ pk11_backupGetSignLength(SECKEYPrivateKey *key) unsigned char buf[20]; /* obviously to small */ CK_ULONG smallLen = sizeof(buf); - mech.mechanism = pk11_mapSignKeyType(key->keyType); + mech.mechanism = PK11_MapSignKeyType(key->keyType); session = pk11_GetNewSession(slot,&owner); if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); @@ -532,11 +550,9 @@ int PK11_SignatureLen(SECKEYPrivateKey *key) { int val; -#ifdef NSS_ENABLE_ECC CK_ATTRIBUTE theTemplate = { CKA_EC_PARAMS, NULL, 0 }; SECItem params = {siBuffer, NULL, 0}; int length; -#endif /* NSS_ENABLE_ECC */ switch (key->keyType) { case rsaKey: @@ -549,7 +565,6 @@ PK11_SignatureLen(SECKEYPrivateKey *key) case fortezzaKey: case dsaKey: return 40; -#ifdef NSS_ENABLE_ECC case ecKey: if (PK11_GetAttributes(NULL, key->pkcs11Slot, key->pkcs11ID, &theTemplate, 1) == CKR_OK) { @@ -563,7 +578,6 @@ PK11_SignatureLen(SECKEYPrivateKey *key) return length; } break; -#endif /* NSS_ENABLE_ECC */ default: break; } @@ -616,7 +630,7 @@ PK11_VerifyRecover(SECKEYPublicKey *key, CK_ULONG len; CK_RV crv; - mech.mechanism = pk11_mapSignKeyType(key->keyType); + mech.mechanism = PK11_MapSignKeyType(key->keyType); if (slot == NULL) { slot = PK11_GetBestSlot(mech.mechanism,wincx); @@ -673,7 +687,7 @@ PK11_Verify(SECKEYPublicKey *key, SECItem *sig, SECItem *hash, void *wincx) CK_SESSION_HANDLE session; CK_RV crv; - mech.mechanism = pk11_mapSignKeyType(key->keyType); + mech.mechanism = PK11_MapSignKeyType(key->keyType); if (slot == NULL) { slot = PK11_GetBestSlot(mech.mechanism,wincx); @@ -729,7 +743,7 @@ PK11_Sign(SECKEYPrivateKey *key, SECItem *sig, SECItem *hash) CK_ULONG len; CK_RV crv; - mech.mechanism = pk11_mapSignKeyType(key->keyType); + mech.mechanism = PK11_MapSignKeyType(key->keyType); if (SECKEY_HAS_ATTRIBUTE_SET(key,CKA_PRIVATE)) { PK11_HandlePasswordCheck(slot, key->wincx); @@ -967,11 +981,17 @@ PK11_UnwrapPrivKey(PK11SlotInfo *slot, PK11SymKey *wrappingKey, if (newKey) { if (perm) { /* Get RW Session will either lock the monitor if necessary, - * or return a thread safe session handle. */ + * or return a thread safe session handle, or fail. */ rwsession = PK11_GetRWSession(slot); } else { rwsession = slot->session; - PK11_EnterSlotMonitor(slot); + if (rwsession != CK_INVALID_SESSION) + PK11_EnterSlotMonitor(slot); + } + if (rwsession == CK_INVALID_SESSION) { + PK11_FreeSymKey(newKey); + PORT_SetError(SEC_ERROR_BAD_DATA); + return NULL; } crv = PK11_GETTAB(slot)->C_UnwrapKey(rwsession, &mechanism, newKey->objectID, @@ -1148,7 +1168,7 @@ PK11_FindGenericObjects(PK11SlotInfo *slot, CK_OBJECT_CLASS objClass) CK_ATTRIBUTE template[1]; CK_ATTRIBUTE *attrs = template; CK_OBJECT_HANDLE *objectIDs = NULL; - PK11GenericObject *lastObj, *obj; + PK11GenericObject *lastObj = NULL, *obj; PK11GenericObject *firstObj = NULL; int i, count = 0; diff --git a/security/nss/lib/pk11wrap/pk11pars.c b/security/nss/lib/pk11wrap/pk11pars.c index 54ebb8227..8644cdccc 100644 --- a/security/nss/lib/pk11wrap/pk11pars.c +++ b/security/nss/lib/pk11wrap/pk11pars.c @@ -137,10 +137,10 @@ SECMOD_CreateModule(const char *library, const char *moduleName, if (slotParams) PORT_Free(slotParams); /* new field */ mod->trustOrder = secmod_argReadLong("trustOrder",nssc, - SFTK_DEFAULT_TRUST_ORDER,NULL); + SECMOD_DEFAULT_TRUST_ORDER,NULL); /* new field */ mod->cipherOrder = secmod_argReadLong("cipherOrder",nssc, - SFTK_DEFAULT_CIPHER_ORDER,NULL); + SECMOD_DEFAULT_CIPHER_ORDER,NULL); /* new field */ mod->isModuleDB = secmod_argHasFlag("flags","moduleDB",nssc); mod->moduleDBOnly = secmod_argHasFlag("flags","moduleDBOnly",nssc); diff --git a/security/nss/lib/pk11wrap/pk11pqg.c b/security/nss/lib/pk11wrap/pk11pqg.c index dd5e5ef3c..62afc7756 100644 --- a/security/nss/lib/pk11wrap/pk11pqg.c +++ b/security/nss/lib/pk11wrap/pk11pqg.c @@ -79,12 +79,16 @@ PK11_PQG_ParamGenSeedLen( unsigned int j, unsigned int seedBytes, PRArenaPool *varena = NULL; PQGParams *params = NULL; PQGVerify *verify = NULL; - CK_ULONG primeBits = j; + CK_ULONG primeBits = PQG_INDEX_TO_PBITS(j); CK_ULONG seedBits = seedBytes*8; *pParams = NULL; *pVfy = NULL; + if (primeBits == (CK_ULONG)-1) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + goto loser; + } PK11_SETATTRS(attrs, CKA_PRIME_BITS,&primeBits,sizeof(primeBits)); attrs++; if (seedBits != 0) { PK11_SETATTRS(attrs, CKA_NETSCAPE_PQG_SEED_BITS, diff --git a/security/nss/lib/pk11wrap/pk11priv.h b/security/nss/lib/pk11wrap/pk11priv.h index 69845b5f5..6d0b012b0 100644 --- a/security/nss/lib/pk11wrap/pk11priv.h +++ b/security/nss/lib/pk11wrap/pk11priv.h @@ -213,6 +213,14 @@ SECStatus pk11_TraverseAllSlots( SECStatus (*callback)(PK11SlotInfo *,void *), SECStatus pk11_RetrieveCrls(CERTCrlHeadNode *nodes, SECItem* issuer, void *wincx); +/* set global options for NSS PKCS#11 module loader */ +SECStatus pk11_setGlobalOptions(PRBool noSingleThreadedModules, + PRBool allowAlreadyInitializedModules, + PRBool dontFinalizeModules); + +/* return whether NSS is allowed to call C_Finalize */ +PRBool pk11_getFinalizeModulesOption(void); + SEC_END_PROTOS #endif diff --git a/security/nss/lib/pk11wrap/pk11pub.h b/security/nss/lib/pk11wrap/pk11pub.h index 51cce7c62..8a933cc93 100644 --- a/security/nss/lib/pk11wrap/pk11pub.h +++ b/security/nss/lib/pk11wrap/pk11pub.h @@ -58,6 +58,7 @@ SEC_BEGIN_PROTOS * Generic Slot Lists Management ************************************************************/ void PK11_FreeSlotList(PK11SlotList *list); +SECStatus PK11_FreeSlotListElement(PK11SlotList *list, PK11SlotListElement *le); PK11SlotListElement * PK11_GetFirstSafe(PK11SlotList *list); PK11SlotListElement *PK11_GetNextSafe(PK11SlotList *list, PK11SlotListElement *le, PRBool restart); @@ -180,6 +181,57 @@ PK11SlotInfo *PK11_GetBestSlotMultiple(CK_MECHANISM_TYPE *type, int count, PK11SlotInfo *PK11_GetBestSlot(CK_MECHANISM_TYPE type, void *wincx); CK_MECHANISM_TYPE PK11_GetBestWrapMechanism(PK11SlotInfo *slot); int PK11_GetBestKeyLength(PK11SlotInfo *slot, CK_MECHANISM_TYPE type); +/* + * Open a new database using the softoken. The caller is responsible for making + * sure the module spec is correct and usable. The caller should ask for one + * new database per call if the caller wants to get meaningful information + * about the new database. + * + * moduleSpec is the same data that you would pass to softoken at + * initialization time under the 'tokens' options. For example, if you were + * to specify tokens=<0x4=[configdir='./mybackup' tokenDescription='Backup']> + * You would specify "configdir='./mybackup' tokenDescription='Backup'" as your + * module spec here. The slot ID will be calculated for you by + * SECMOD_OpenUserDB(). + * + * Typical parameters here are configdir, tokenDescription and flags. + * + * a Full list is below: + * + * + * configDir - The location of the databases for this token. If configDir is + * not specified, and noCertDB and noKeyDB is not specified, the load + * will fail. + * certPrefix - Cert prefix for this token. + * keyPrefix - Prefix for the key database for this token. (if not specified, + * certPrefix will be used). + * tokenDescription - The label value for this token returned in the + * CK_TOKEN_INFO structure with an internationalize string (UTF8). + * This value will be truncated at 32 bytes (no NULL, partial UTF8 + * characters dropped). You should specify a user friendly name here + * as this is the value the token will be refered to in most + * application UI's. You should make sure tokenDescription is unique. + * slotDescription - The slotDescription value for this token returned + * in the CK_SLOT_INFO structure with an internationalize string + * (UTF8). This value will be truncated at 64 bytes (no NULL, partial + * UTF8 characters dropped). This name will not change after the + * database is closed. It should have some number to make this unique. + * minPWLen - minimum password length for this token. + * flags - comma separated list of flag values, parsed case-insensitive. + * Valid flags are: + * readOnly - Databases should be opened read only. + * noCertDB - Don't try to open a certificate database. + * noKeyDB - Don't try to open a key database. + * forceOpen - Don't fail to initialize the token if the + * databases could not be opened. + * passwordRequired - zero length passwords are not acceptable + * (valid only if there is a keyDB). + * optimizeSpace - allocate smaller hash tables and lock tables. + * When this flag is not specified, Softoken will allocate + * large tables to prevent lock contention. + */ +PK11SlotInfo *SECMOD_OpenUserDB(const char *moduleSpec); +SECStatus SECMOD_CloseUserDB(PK11SlotInfo *slot); /********************************************************************* * Mechanism Mapping functions @@ -201,12 +253,14 @@ SECOidTag PK11_FortezzaMapSig(SECOidTag algTag); SECStatus PK11_ParamToAlgid(SECOidTag algtag, SECItem *param, PRArenaPool *arena, SECAlgorithmID *algid); SECStatus PK11_SeedRandom(PK11SlotInfo *,unsigned char *data,int len); +SECStatus PK11_GenerateRandomOnSlot(PK11SlotInfo *,unsigned char *data,int len); SECStatus PK11_RandomUpdate(void *data, size_t bytes); SECStatus PK11_GenerateRandom(unsigned char *data,int len); CK_RV PK11_MapPBEMechanismToCryptoMechanism(CK_MECHANISM_PTR pPBEMechanism, CK_MECHANISM_PTR pCryptoMechanism, SECItem *pbe_pwd, PRBool bad3DES); CK_MECHANISM_TYPE PK11_GetPadMechanism(CK_MECHANISM_TYPE); +CK_MECHANISM_TYPE PK11_MapSignKeyType(KeyType keyType); /********************************************************************** * Symetric, Public, and Private Keys @@ -245,6 +299,39 @@ PK11SymKey * PK11_ListFixedKeysInSlot(PK11SlotInfo *slot, char *nickname, PK11SymKey *PK11_GetNextSymKey(PK11SymKey *symKey); CK_KEY_TYPE PK11_GetSymKeyType(PK11SymKey *key); +/* + * PK11_SetSymKeyUserData + * sets generic user data on keys (usually a pointer to a data structure) + * that can later be retrieved by PK11_GetSymKeyUserData(). + * symKey - key where data will be set. + * data - data to be set. + * freefunc - function used to free the data. + * Setting user data on symKeys with existing user data already set will cause + * the existing user data to be freed before the new user data is set. + * Freeing user data is done by calling the user specified freefunc. + * If freefunc is NULL, the user data is assumed to be global or static an + * not freed. Passing NULL for user data to PK11_SetSymKeyUserData has the + * effect of freeing any existing user data, and clearing the user data + * pointer. If user data exists when the symKey is finally freed, that + * data will be freed with freefunc. + * + * Applications should only use this function on keys which the application + * has created directly, as there is only one user data value per key. + */ +void PK11_SetSymKeyUserData(PK11SymKey *symKey, void *data, + PK11FreeDataFunc freefunc); +/* PK11_GetSymKeyUserData + * retrieves generic user data which was set on a key by + * PK11_SetSymKeyUserData. + * symKey - key with data to be fetched + * + * If no data exists, or the data has been cleared, PK11_GetSymKeyUserData + * will return NULL. Returned data is still owned and managed by the SymKey, + * the caller should not free the data. + * + */ +void *PK11_GetSymKeyUserData(PK11SymKey *symKey); + SECStatus PK11_PubWrapSymKey(CK_MECHANISM_TYPE type, SECKEYPublicKey *pubKey, PK11SymKey *symKey, SECItem *wrappedKey); SECStatus PK11_WrapSymKey(CK_MECHANISM_TYPE type, SECItem *params, @@ -440,6 +527,8 @@ PK11SymKey *PK11_ConvertSessionSymKeyToTokenSymKey(PK11SymKey *symk, void *wincx); SECKEYPrivateKey *PK11_ConvertSessionPrivKeyToTokenPrivKey( SECKEYPrivateKey *privk, void* wincx); +SECKEYPrivateKey * PK11_CopyTokenPrivKeyToSessionPrivKey(PK11SlotInfo *destSlot, + SECKEYPrivateKey *privKey); /********************************************************************** * Certs @@ -585,7 +674,7 @@ SECStatus PK11_UpdateSlotAttribute(PK11SlotInfo *, PK11DefaultArrayEntry *, PK11GenericObject *PK11_FindGenericObjects(PK11SlotInfo *slot, CK_OBJECT_CLASS objClass); PK11GenericObject *PK11_GetNextGenericObject(PK11GenericObject *object); -PK11GenericObject *PK11_GetPrevtGenericObject(PK11GenericObject *object); +PK11GenericObject *PK11_GetPrevGenericObject(PK11GenericObject *object); SECStatus PK11_UnlinkGenericObject(PK11GenericObject *object); SECStatus PK11_LinkGenericObject(PK11GenericObject *list, PK11GenericObject *object); diff --git a/security/nss/lib/pk11wrap/pk11skey.c b/security/nss/lib/pk11wrap/pk11skey.c index 299702a48..ce5cbd811 100644 --- a/security/nss/lib/pk11wrap/pk11skey.c +++ b/security/nss/lib/pk11wrap/pk11skey.c @@ -69,45 +69,94 @@ pk11_ExitKeyMonitor(PK11SymKey *symKey) { PK11_ExitSlotMonitor(symKey->slot); } - +/* + * pk11_getKeyFromList returns a symKey that has a session (if needSession + * was specified), or explicitly does not have a session (if needSession + * was not specified). + */ static PK11SymKey * -pk11_getKeyFromList(PK11SlotInfo *slot) { +pk11_getKeyFromList(PK11SlotInfo *slot, PRBool needSession) { PK11SymKey *symKey = NULL; PZ_Lock(slot->freeListLock); - if (slot->freeSymKeysHead) { - symKey = slot->freeSymKeysHead; - slot->freeSymKeysHead = symKey->next; - slot->keyCount--; + /* own session list are symkeys with sessions that the symkey owns. + * 'most' symkeys will own their own session. */ + if (needSession) { + if (slot->freeSymKeysWithSessionHead) { + symKey = slot->freeSymKeysWithSessionHead; + slot->freeSymKeysWithSessionHead = symKey->next; + slot->keyCount--; + } + } + /* if we don't need a symkey with its own session, or we couldn't find + * one on the owner list, get one from the non-owner free list. */ + if (!symKey) { + if (slot->freeSymKeysHead) { + symKey = slot->freeSymKeysHead; + slot->freeSymKeysHead = symKey->next; + slot->keyCount--; + } } PZ_Unlock(slot->freeListLock); if (symKey) { symKey->next = NULL; - if ((symKey->series != slot->series) || (!symKey->sessionOwner)) - symKey->session = pk11_GetNewSession(slot,&symKey->sessionOwner); - return symKey; + if (!needSession) { + return symKey; + } + /* if we are getting an owner key, make sure we have a valid session. + * session could be invalid if the token has been removed or because + * we got it from the non-owner free list */ + if ((symKey->series != slot->series) || + (symKey->session == CK_INVALID_SESSION)) { + symKey->session = pk11_GetNewSession(slot, &symKey->sessionOwner); + } + PORT_Assert(symKey->session != CK_INVALID_SESSION); + if (symKey->session != CK_INVALID_SESSION) + return symKey; + PK11_FreeSymKey(symKey); + /* if we are here, we need a session, but couldn't get one, it's + * unlikely we pk11_GetNewSession will succeed if we call it a second + * time. */ + return NULL; } symKey = PORT_New(PK11SymKey); if (symKey == NULL) { return NULL; } - symKey->session = pk11_GetNewSession(slot,&symKey->sessionOwner); + symKey->next = NULL; + if (needSession) { + symKey->session = pk11_GetNewSession(slot,&symKey->sessionOwner); + PORT_Assert(symKey->session != CK_INVALID_SESSION); + if (symKey->session == CK_INVALID_SESSION) { + PK11_FreeSymKey(symKey); + symKey = NULL; + } + } else { + symKey->session = CK_INVALID_SESSION; + } return symKey; } +/* Caller MUST hold slot->freeListLock (or ref count == 0?) !! */ void PK11_CleanKeyList(PK11SlotInfo *slot) { PK11SymKey *symKey = NULL; + while (slot->freeSymKeysWithSessionHead) { + symKey = slot->freeSymKeysWithSessionHead; + slot->freeSymKeysWithSessionHead = symKey->next; + pk11_CloseSession(slot, symKey->session, symKey->sessionOwner); + PORT_Free(symKey); + } while (slot->freeSymKeysHead) { symKey = slot->freeSymKeysHead; slot->freeSymKeysHead = symKey->next; - pk11_CloseSession(slot, symKey->session,symKey->sessionOwner); + pk11_CloseSession(slot, symKey->session, symKey->sessionOwner); PORT_Free(symKey); - }; + } return; } @@ -115,18 +164,29 @@ PK11_CleanKeyList(PK11SlotInfo *slot) * create a symetric key: * Slot is the slot to create the key in. * type is the mechanism type + * owner is does this symKey structure own it's object handle (rare + * that this is false). + * needSession means the returned symKey will return with a valid session + * allocated already. */ static PK11SymKey * -pk11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, PRBool owner, - void *wincx) +pk11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, + PRBool owner, PRBool needSession, void *wincx) { - PK11SymKey *symKey = pk11_getKeyFromList(slot); - + PK11SymKey *symKey = pk11_getKeyFromList(slot, needSession); if (symKey == NULL) { return NULL; } + /* if needSession was specified, make sure we have a valid session. + * callers which specify needSession as false should do their own + * check of the session before returning the symKey */ + if (needSession && symKey->session == CK_INVALID_SESSION) { + PK11_FreeSymKey(symKey); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return NULL; + } symKey->type = type; symKey->data.type = siBuffer; @@ -141,6 +201,8 @@ pk11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, PRBool owner, symKey->refCount = 1; symKey->origin = PK11_OriginNULL; symKey->parent = NULL; + symKey->freeFunc = NULL; + symKey->userData = NULL; PK11_ReferenceSlot(slot); return symKey; } @@ -168,11 +230,33 @@ PK11_FreeSymKey(PK11SymKey *symKey) PORT_Memset(symKey->data.data, 0, symKey->data.len); PORT_Free(symKey->data.data); } + /* free any existing data */ + if (symKey->userData && symKey->freeFunc) { + (*symKey->freeFunc)(symKey->userData); + } slot = symKey->slot; PZ_Lock(slot->freeListLock); if (slot->keyCount < slot->maxKeyCount) { - symKey->next = slot->freeSymKeysHead; - slot->freeSymKeysHead = symKey; + /* + * freeSymkeysWithSessionHead contain a list of reusable + * SymKey structures with valid sessions. + * sessionOwner must be true. + * session must be valid. + * freeSymKeysHead contain a list of SymKey structures without + * valid session. + * session must be CK_INVALID_SESSION. + * though sessionOwner is false, callers should not depend on + * this fact. + */ + if (symKey->sessionOwner) { + PORT_Assert (symKey->session != CK_INVALID_SESSION); + symKey->next = slot->freeSymKeysWithSessionHead; + slot->freeSymKeysWithSessionHead = symKey; + } else { + symKey->session = CK_INVALID_SESSION; + symKey->next = slot->freeSymKeysHead; + slot->freeSymKeysHead = symKey; + } slot->keyCount++; symKey->slot = NULL; freeit = PR_FALSE; @@ -239,6 +323,25 @@ PK11_SetSymKeyNickname(PK11SymKey *symKey, const char *nickname) return PK11_SetObjectNickname(symKey->slot,symKey->objectID,nickname); } +void * +PK11_GetSymKeyUserData(PK11SymKey *symKey) +{ + return symKey->userData; +} + +void +PK11_SetSymKeyUserData(PK11SymKey *symKey, void *userData, + PK11FreeDataFunc freeFunc) +{ + /* free any existing data */ + if (symKey->userData && symKey->freeFunc) { + (*symKey->freeFunc)(symKey->userData); + } + symKey->userData = userData; + symKey->freeFunc = freeFunc; + return; +} + /* * turn key handle into an appropriate key object */ @@ -247,12 +350,13 @@ PK11_SymKeyFromHandle(PK11SlotInfo *slot, PK11SymKey *parent, PK11Origin origin, CK_MECHANISM_TYPE type, CK_OBJECT_HANDLE keyID, PRBool owner, void *wincx) { PK11SymKey *symKey; + PRBool needSession = !(owner && parent); if (keyID == CK_INVALID_HANDLE) { return NULL; } - symKey = pk11_CreateSymKey(slot,type,owner,wincx); + symKey = pk11_CreateSymKey(slot, type, owner, needSession, wincx); if (symKey == NULL) { return NULL; } @@ -264,11 +368,19 @@ PK11_SymKeyFromHandle(PK11SlotInfo *slot, PK11SymKey *parent, PK11Origin origin, /* This is only used by SSL. What we really want here is a session * structure with a ref count so the session goes away only after all the * keys do. */ - if (owner && parent) { - pk11_CloseSession(symKey->slot, symKey->session,symKey->sessionOwner); + if (!needSession) { symKey->sessionOwner = PR_FALSE; symKey->session = parent->session; symKey->parent = PK11_ReferenceSymKey(parent); + /* This is the only case where pk11_CreateSymKey does not explicitly + * check symKey->session. We need to assert here to make sure. + * the session isn't invalid. */ + PORT_Assert(parent->session != CK_INVALID_SESSION); + if (parent->session == CK_INVALID_SESSION) { + PK11_FreeSymKey(symKey); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return NULL; + } } return symKey; @@ -329,7 +441,7 @@ pk11_ImportSymKeyWithTempl(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, PK11SymKey * symKey; SECStatus rv; - symKey = pk11_CreateSymKey(slot,type,!isToken,wincx); + symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE, wincx); if (symKey == NULL) { return NULL; } @@ -828,11 +940,11 @@ PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, return NULL; } - symKey = pk11_CreateSymKey(bestSlot, type, !isToken, wincx); + symKey = pk11_CreateSymKey(bestSlot, type, !isToken, PR_TRUE, wincx); PK11_FreeSlot(bestSlot); } else { - symKey = pk11_CreateSymKey(slot, type, !isToken, wincx); + symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE, wincx); } if (symKey == NULL) return NULL; @@ -857,11 +969,18 @@ PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, /* Get session and perform locking */ if (isToken) { PK11_Authenticate(symKey->slot,PR_TRUE,wincx); - session = PK11_GetRWSession(symKey->slot); /* Should always be original slot */ + /* Should always be original slot */ + session = PK11_GetRWSession(symKey->slot); symKey->owner = PR_FALSE; } else { session = symKey->session; - pk11_EnterKeyMonitor(symKey); + if (session != CK_INVALID_SESSION) + pk11_EnterKeyMonitor(symKey); + } + if (session == CK_INVALID_SESSION) { + PK11_FreeSymKey(symKey); + PORT_SetError(SEC_ERROR_BAD_DATA); + return NULL; } crv = PK11_GETTAB(symKey->slot)->C_GenerateKey(session, @@ -897,108 +1016,25 @@ PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, int keySize, SECItem *keyid, PRBool isToken, void *wincx) { PK11SymKey *symKey; - CK_ATTRIBUTE genTemplate[6]; - CK_ATTRIBUTE *attrs = genTemplate; - int count = sizeof(genTemplate)/sizeof(genTemplate[0]); - CK_SESSION_HANDLE session; - CK_MECHANISM mechanism; - CK_RV crv; PRBool weird = PR_FALSE; /* hack for fortezza */ - CK_BBOOL cktrue = CK_TRUE; - CK_ULONG ck_key_size; /* only used for variable-length keys */ + CK_FLAGS opFlags = CKF_SIGN; + PK11AttrFlags attrFlags = 0; if ((keySize == -1) && (type == CKM_SKIPJACK_CBC64)) { weird = PR_TRUE; keySize = 0; } - /* TNH: Isn't this redundant, since "handleKey" will set defaults? */ - PK11_SETATTRS(attrs, (!weird) - ? CKA_ENCRYPT : CKA_DECRYPT, &cktrue, sizeof(CK_BBOOL)); attrs++; - - if (keySize != 0) { - ck_key_size = keySize; /* Convert to PK11 type */ - - PK11_SETATTRS(attrs, CKA_VALUE_LEN, &ck_key_size, sizeof(ck_key_size)); - attrs++; - } - - /* Include key id value if provided */ - if (keyid) { - PK11_SETATTRS(attrs, CKA_ID, keyid->data, keyid->len); attrs++; - } - - if (isToken) { - PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue)); attrs++; - PK11_SETATTRS(attrs, CKA_PRIVATE, &cktrue, sizeof(cktrue)); attrs++; - } - - PK11_SETATTRS(attrs, CKA_SIGN, &cktrue, sizeof(cktrue)); attrs++; - - count = attrs - genTemplate; - PR_ASSERT(count <= sizeof(genTemplate)/sizeof(CK_ATTRIBUTE)); - - /* find a slot to generate the key into */ - /* Only do slot management if this is not a token key */ - if (!isToken && (slot == NULL || !PK11_DoesMechanism(slot,type))) { - PK11SlotInfo *bestSlot; - - bestSlot = PK11_GetBestSlot(type,wincx); - if (bestSlot == NULL) { - PORT_SetError( SEC_ERROR_NO_MODULE ); - return NULL; - } - - symKey = pk11_CreateSymKey(bestSlot, type, !isToken, wincx); - - PK11_FreeSlot(bestSlot); - } else { - symKey = pk11_CreateSymKey(slot, type, !isToken, wincx); - } - if (symKey == NULL) return NULL; - - symKey->size = keySize; - symKey->origin = (!weird) ? PK11_OriginGenerated : PK11_OriginFortezzaHack; + opFlags |= weird ? CKF_DECRYPT : CKF_ENCRYPT; - /* Initialize the Key Gen Mechanism */ - mechanism.mechanism = PK11_GetKeyGenWithSize(type, keySize); - if (mechanism.mechanism == CKM_FAKE_RANDOM) { - PORT_SetError( SEC_ERROR_NO_MODULE ); - return NULL; - } - - /* Set the parameters for the key gen if provided */ - mechanism.pParameter = NULL; - mechanism.ulParameterLen = 0; - if (param) { - mechanism.pParameter = param->data; - mechanism.ulParameterLen = param->len; - } - - /* Get session and perform locking */ if (isToken) { - PK11_Authenticate(symKey->slot,PR_TRUE,wincx); - session = PK11_GetRWSession(symKey->slot); /* Should always be original slot */ - symKey->owner = PR_FALSE; - } else { - session = symKey->session; - pk11_EnterKeyMonitor(symKey); - } - - crv = PK11_GETTAB(symKey->slot)->C_GenerateKey(session, - &mechanism, genTemplate, count, &symKey->objectID); - - /* Release lock and session */ - if (isToken) { - PK11_RestoreROSession(symKey->slot, session); - } else { - pk11_ExitKeyMonitor(symKey); + attrFlags |= (PK11_ATTR_TOKEN | PK11_ATTR_PRIVATE); } - if (crv != CKR_OK) { - PK11_FreeSymKey(symKey); - PORT_SetError( PK11_MapError(crv) ); - return NULL; + symKey = PK11_TokenKeyGenWithFlags(slot, type, param, keySize, keyid, + opFlags, attrFlags, wincx); + if (symKey && weird) { + PK11_SetFortezzaHack(symKey); } return symKey; @@ -1033,6 +1069,10 @@ PK11_ConvertSessionSymKeyToTokenSymKey(PK11SymKey *symk, void *wincx) PK11_Authenticate(slot, PR_TRUE, wincx); rwsession = PK11_GetRWSession(slot); + if (rwsession == CK_INVALID_SESSION) { + PORT_SetError(SEC_ERROR_BAD_DATA); + return NULL; + } crv = PK11_GETTAB(slot)->C_CopyObject(rwsession, symk->objectID, template, 1, &newKeyID); PK11_RestoreROSession(slot, rwsession); @@ -1297,7 +1337,7 @@ PK11_DeriveWithFlagsPerm( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, int keySize, CK_FLAGS flags, PRBool isPerm) { CK_BBOOL cktrue = CK_TRUE; - CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS+1]; + CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; CK_ATTRIBUTE *attrs; unsigned int templateCount = 0; @@ -1376,14 +1416,15 @@ pk11_DeriveWithTemplate( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, newBaseKey = pk11_CopyToSlot (newSlot, derive, CKA_DERIVE, baseKey); PK11_FreeSlot(newSlot); - if (newBaseKey == NULL) return NULL; + if (newBaseKey == NULL) + return NULL; baseKey = newBaseKey; slot = baseKey->slot; } /* get our key Structure */ - symKey = pk11_CreateSymKey(slot,target,!isPerm,baseKey->cx); + symKey = pk11_CreateSymKey(slot, target, !isPerm, PR_TRUE, baseKey->cx); if (symKey == NULL) { return NULL; } @@ -1406,15 +1447,21 @@ pk11_DeriveWithTemplate( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, pk11_EnterKeyMonitor(symKey); session = symKey->session; } - crv = PK11_GETTAB(slot)->C_DeriveKey(session, &mechanism, - baseKey->objectID, keyTemplate, templateCount, &symKey->objectID); - if (isPerm) { - PK11_RestoreROSession(slot, session); + if (session == CK_INVALID_SESSION) { + if (!isPerm) + pk11_ExitKeyMonitor(symKey); + crv = CKR_SESSION_HANDLE_INVALID; } else { - pk11_ExitKeyMonitor(symKey); + crv = PK11_GETTAB(slot)->C_DeriveKey(session, &mechanism, + baseKey->objectID, keyTemplate, templateCount, &symKey->objectID); + if (isPerm) { + PK11_RestoreROSession(slot, session); + } else { + pk11_ExitKeyMonitor(symKey); + } } - - if (newBaseKey) PK11_FreeSymKey(newBaseKey); + if (newBaseKey) + PK11_FreeSymKey(newBaseKey); if (crv != CKR_OK) { PK11_FreeSymKey(symKey); return NULL; @@ -1450,7 +1497,7 @@ PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, } /* get our key Structure */ - symKey = pk11_CreateSymKey(slot,target,PR_TRUE,wincx); + symKey = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, wincx); if (symKey == NULL) { return NULL; } @@ -1540,7 +1587,6 @@ PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, PORT_SetError( PK11_MapError(crv) ); } break; -#ifdef NSS_ENABLE_ECC case ecKey: { CK_BBOOL cktrue = CK_TRUE; @@ -1594,10 +1640,6 @@ PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, if (crv == CKR_OK) return symKey; PORT_SetError( PK11_MapError(crv) ); } -#else - case ecKey: - break; -#endif /* NSS_ENABLE_ECC */ } PK11_FreeSymKey(symKey); @@ -1613,13 +1655,11 @@ PK11_PubDeriveWithKDF(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, { PK11SlotInfo *slot = privKey->pkcs11Slot; PK11SymKey *symKey; -#ifdef NSS_ENABLE_ECC CK_MECHANISM mechanism; CK_RV crv; -#endif /* get our key Structure */ - symKey = pk11_CreateSymKey(slot,target,PR_TRUE,wincx); + symKey = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, wincx); if (symKey == NULL) { return NULL; } @@ -1636,7 +1676,6 @@ PK11_PubDeriveWithKDF(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, PK11_FreeSymKey(symKey); return PK11_PubDerive(privKey, pubKey, isSender, randomA, randomB, derive, target, operation, keySize, wincx); -#ifdef NSS_ENABLE_ECC case ecKey: { CK_BBOOL cktrue = CK_TRUE; @@ -1699,10 +1738,6 @@ PK11_PubDeriveWithKDF(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, if (crv == CKR_OK) return symKey; PORT_SetError( PK11_MapError(crv) ); } -#else - case ecKey: - break; -#endif /* NSS_ENABLE_ECC */ } PK11_FreeSymKey(symKey); @@ -1908,7 +1943,7 @@ pk11_AnyUnwrapKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE wrappingKey, } /* get our key Structure */ - symKey = pk11_CreateSymKey(slot,target,!isPerm,wincx); + symKey = pk11_CreateSymKey(slot, target, !isPerm, PR_TRUE, wincx); if (symKey == NULL) { if (param_free) SECITEM_FreeItem(param_free,PR_TRUE); return NULL; @@ -1923,11 +1958,16 @@ pk11_AnyUnwrapKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE wrappingKey, pk11_EnterKeyMonitor(symKey); rwsession = symKey->session; } - crv = PK11_GETTAB(slot)->C_UnwrapKey(rwsession,&mechanism,wrappingKey, + PORT_Assert(rwsession != CK_INVALID_SESSION); + if (rwsession == CK_INVALID_SESSION) + crv = CKR_SESSION_HANDLE_INVALID; + else + crv = PK11_GETTAB(slot)->C_UnwrapKey(rwsession,&mechanism,wrappingKey, wrappedKey->data, wrappedKey->len, keyTemplate, templateCount, &symKey->objectID); if (isPerm) { - PK11_RestoreROSession(slot, rwsession); + if (rwsession != CK_INVALID_SESSION) + PK11_RestoreROSession(slot, rwsession); } else { pk11_ExitKeyMonitor(symKey); } diff --git a/security/nss/lib/pk11wrap/pk11slot.c b/security/nss/lib/pk11wrap/pk11slot.c index 201959f18..a92fbf7df 100644 --- a/security/nss/lib/pk11wrap/pk11slot.c +++ b/security/nss/lib/pk11wrap/pk11slot.c @@ -145,11 +145,16 @@ PK11_NewSlotList(void) /* * free a list element when all the references go away. */ -static void -pk11_FreeListElement(PK11SlotList *list, PK11SlotListElement *le) +SECStatus +PK11_FreeSlotListElement(PK11SlotList *list, PK11SlotListElement *le) { PRBool freeit = PR_FALSE; + if (list == NULL || le == NULL) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + PZ_Lock(list->lock); if (le->refCount-- == 1) { freeit = PR_TRUE; @@ -159,23 +164,34 @@ pk11_FreeListElement(PK11SlotList *list, PK11SlotListElement *le) PK11_FreeSlot(le->slot); PORT_Free(le); } + return SECSuccess; } -/* - * if we are freeing the list, we must be the only ones with a pointer - * to the list. - */ -void -PK11_FreeSlotList(PK11SlotList *list) +static void +pk11_FreeSlotListStatic(PK11SlotList *list) { PK11SlotListElement *le, *next ; if (list == NULL) return; for (le = list->head ; le; le = next) { next = le->next; - pk11_FreeListElement(list,le); + PK11_FreeSlotListElement(list,le); + } + if (list->lock) { + PZ_DestroyLock(list->lock); } - PZ_DestroyLock(list->lock); + list->lock = NULL; + list->head = NULL; +} + +/* + * if we are freeing the list, we must be the only ones with a pointer + * to the list. + */ +void +PK11_FreeSlotList(PK11SlotList *list) +{ + pk11_FreeSlotListStatic(list); PORT_Free(list); } @@ -213,7 +229,7 @@ PK11_DeleteSlotFromList(PK11SlotList *list,PK11SlotListElement *le) if (le->next) le->next->prev = le->prev; else list->tail = le->prev; le->next = le->prev = NULL; PZ_Unlock(list->lock); - pk11_FreeListElement(list,le); + PK11_FreeSlotListElement(list,le); return SECSuccess; } @@ -259,7 +275,7 @@ PK11_GetNextRef(PK11SlotList *list, PK11SlotListElement *le, PRBool restart) PK11SlotListElement *new_le; new_le = le->next; if (new_le) new_le->refCount++; - pk11_FreeListElement(list,le); + PK11_FreeSlotListElement(list,le); return new_le; } @@ -300,7 +316,7 @@ PK11_GetNextSafe(PK11SlotList *list, PK11SlotListElement *le, PRBool restart) } if (new_le) new_le->refCount++; PZ_Unlock(list->lock); - pk11_FreeListElement(list,le); + PK11_FreeSlotListElement(list,le); return new_le; } @@ -348,6 +364,7 @@ PK11_NewSlotInfo(SECMODModule *mod) PORT_Free(slot); return slot; } + slot->freeSymKeysWithSessionHead = NULL; slot->freeSymKeysHead = NULL; slot->keyCount = 0; slot->maxKeyCount = 0; @@ -650,36 +667,53 @@ CK_SESSION_HANDLE PK11_GetRWSession(PK11SlotInfo *slot) { CK_SESSION_HANDLE rwsession; CK_RV crv; + PRBool haveMonitor = PR_FALSE; - if (!slot->isThreadSafe || slot->defRWSession) PK11_EnterSlotMonitor(slot); - if (slot->defRWSession) return slot->session; + if (!slot->isThreadSafe || slot->defRWSession) { + PK11_EnterSlotMonitor(slot); + haveMonitor = PR_TRUE; + } + if (slot->defRWSession) { + PORT_Assert(slot->session != CK_INVALID_SESSION); + if (slot->session != CK_INVALID_SESSION) + return slot->session; + } crv = PK11_GETTAB(slot)->C_OpenSession(slot->slotID, CKF_RW_SESSION|CKF_SERIAL_SESSION, slot, pk11_notify,&rwsession); - if (crv == CKR_SESSION_COUNT) { - PK11_GETTAB(slot)->C_CloseSession(slot->session); - slot->session = CK_INVALID_SESSION; - crv = PK11_GETTAB(slot)->C_OpenSession(slot->slotID, - CKF_RW_SESSION|CKF_SERIAL_SESSION, - slot,pk11_notify,&rwsession); - } - if (crv != CKR_OK) { + PORT_Assert(rwsession != CK_INVALID_SESSION || crv != CKR_OK); + if (crv != CKR_OK || rwsession == CK_INVALID_SESSION) { + if (crv == CKR_OK) + crv = CKR_DEVICE_ERROR; + if (haveMonitor) + PK11_ExitSlotMonitor(slot); PORT_SetError(PK11_MapError(crv)); - if (slot->session == CK_INVALID_SESSION) { - PK11_GETTAB(slot)->C_OpenSession(slot->slotID,CKF_SERIAL_SESSION, - slot,pk11_notify,&slot->session); - } - if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); return CK_INVALID_SESSION; } - + if (slot->defRWSession) { /* we have the monitor */ + slot->session = rwsession; + } return rwsession; } PRBool -PK11_RWSessionHasLock(PK11SlotInfo *slot,CK_SESSION_HANDLE session_handle) { - return (PRBool)(!slot->isThreadSafe || slot->defRWSession); +PK11_RWSessionHasLock(PK11SlotInfo *slot,CK_SESSION_HANDLE session_handle) +{ + PRBool hasLock; + hasLock = (PRBool)(!slot->isThreadSafe || + (slot->defRWSession && slot->session != CK_INVALID_SESSION)); + return hasLock; +} + +static PRBool +pk11_RWSessionIsDefault(PK11SlotInfo *slot,CK_SESSION_HANDLE rwsession) +{ + PRBool isDefault; + isDefault = (PRBool)(slot->session == rwsession && + slot->defRWSession && + slot->session != CK_INVALID_SESSION); + return isDefault; } /* @@ -690,16 +724,14 @@ PK11_RWSessionHasLock(PK11SlotInfo *slot,CK_SESSION_HANDLE session_handle) { void PK11_RestoreROSession(PK11SlotInfo *slot,CK_SESSION_HANDLE rwsession) { - if (slot->defRWSession) { - PK11_ExitSlotMonitor(slot); - return; - } - PK11_GETTAB(slot)->C_CloseSession(rwsession); - if (slot->session == CK_INVALID_SESSION) { - PK11_GETTAB(slot)->C_OpenSession(slot->slotID,CKF_SERIAL_SESSION, - slot,pk11_notify,&slot->session); + PORT_Assert(rwsession != CK_INVALID_SESSION); + if (rwsession != CK_INVALID_SESSION) { + PRBool doExit = PK11_RWSessionHasLock(slot, rwsession); + if (!pk11_RWSessionIsDefault(slot, rwsession)) + PK11_GETTAB(slot)->C_CloseSession(rwsession); + if (doExit) + PK11_ExitSlotMonitor(slot); } - if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); } /************************************************************ @@ -709,75 +741,59 @@ PK11_RestoreROSession(PK11SlotInfo *slot,CK_SESSION_HANDLE rwsession) /* Init the static built int slot list (should actually integrate * with PK11_NewSlotList */ static void -pk11_initSlotList(PK11SlotList *list) +pk11_InitSlotListStatic(PK11SlotList *list) { list->lock = PZ_NewLock(nssILockList); list->head = NULL; } -static void -pk11_freeSlotList(PK11SlotList *list) -{ - PK11SlotListElement *le, *next ; - if (list == NULL) return; - - for (le = list->head ; le; le = next) { - next = le->next; - pk11_FreeListElement(list,le); - } - if (list->lock) { - PZ_DestroyLock(list->lock); - } - list->lock = NULL; - list->head = NULL; -} /* initialize the system slotlists */ SECStatus PK11_InitSlotLists(void) { - pk11_initSlotList(&pk11_aesSlotList); - pk11_initSlotList(&pk11_desSlotList); - pk11_initSlotList(&pk11_rc4SlotList); - pk11_initSlotList(&pk11_rc2SlotList); - pk11_initSlotList(&pk11_rc5SlotList); - pk11_initSlotList(&pk11_md5SlotList); - pk11_initSlotList(&pk11_md2SlotList); - pk11_initSlotList(&pk11_sha1SlotList); - pk11_initSlotList(&pk11_rsaSlotList); - pk11_initSlotList(&pk11_dsaSlotList); - pk11_initSlotList(&pk11_dhSlotList); - pk11_initSlotList(&pk11_ecSlotList); - pk11_initSlotList(&pk11_ideaSlotList); - pk11_initSlotList(&pk11_sslSlotList); - pk11_initSlotList(&pk11_tlsSlotList); - pk11_initSlotList(&pk11_randomSlotList); - pk11_initSlotList(&pk11_sha256SlotList); - pk11_initSlotList(&pk11_sha512SlotList); + pk11_InitSlotListStatic(&pk11_aesSlotList); + pk11_InitSlotListStatic(&pk11_desSlotList); + pk11_InitSlotListStatic(&pk11_rc4SlotList); + pk11_InitSlotListStatic(&pk11_rc2SlotList); + pk11_InitSlotListStatic(&pk11_rc5SlotList); + pk11_InitSlotListStatic(&pk11_md5SlotList); + pk11_InitSlotListStatic(&pk11_md2SlotList); + pk11_InitSlotListStatic(&pk11_sha1SlotList); + pk11_InitSlotListStatic(&pk11_rsaSlotList); + pk11_InitSlotListStatic(&pk11_dsaSlotList); + pk11_InitSlotListStatic(&pk11_dhSlotList); + pk11_InitSlotListStatic(&pk11_ecSlotList); + pk11_InitSlotListStatic(&pk11_ideaSlotList); + pk11_InitSlotListStatic(&pk11_sslSlotList); + pk11_InitSlotListStatic(&pk11_tlsSlotList); + pk11_InitSlotListStatic(&pk11_randomSlotList); + pk11_InitSlotListStatic(&pk11_sha256SlotList); + pk11_InitSlotListStatic(&pk11_sha512SlotList); return SECSuccess; } void PK11_DestroySlotLists(void) { - pk11_freeSlotList(&pk11_aesSlotList); - pk11_freeSlotList(&pk11_desSlotList); - pk11_freeSlotList(&pk11_rc4SlotList); - pk11_freeSlotList(&pk11_rc2SlotList); - pk11_freeSlotList(&pk11_rc5SlotList); - pk11_freeSlotList(&pk11_md5SlotList); - pk11_freeSlotList(&pk11_md2SlotList); - pk11_freeSlotList(&pk11_sha1SlotList); - pk11_freeSlotList(&pk11_rsaSlotList); - pk11_freeSlotList(&pk11_dsaSlotList); - pk11_freeSlotList(&pk11_dhSlotList); - pk11_freeSlotList(&pk11_ecSlotList); - pk11_freeSlotList(&pk11_ideaSlotList); - pk11_freeSlotList(&pk11_sslSlotList); - pk11_freeSlotList(&pk11_tlsSlotList); - pk11_freeSlotList(&pk11_randomSlotList); - pk11_freeSlotList(&pk11_sha256SlotList); - pk11_freeSlotList(&pk11_sha512SlotList); + pk11_FreeSlotListStatic(&pk11_aesSlotList); + pk11_FreeSlotListStatic(&pk11_desSlotList); + pk11_FreeSlotListStatic(&pk11_rc4SlotList); + pk11_FreeSlotListStatic(&pk11_rc2SlotList); + pk11_FreeSlotListStatic(&pk11_rc5SlotList); + pk11_FreeSlotListStatic(&pk11_md5SlotList); + pk11_FreeSlotListStatic(&pk11_md2SlotList); + pk11_FreeSlotListStatic(&pk11_sha1SlotList); + pk11_FreeSlotListStatic(&pk11_rsaSlotList); + pk11_FreeSlotListStatic(&pk11_dsaSlotList); + pk11_FreeSlotListStatic(&pk11_dhSlotList); + pk11_FreeSlotListStatic(&pk11_ecSlotList); + pk11_FreeSlotListStatic(&pk11_ideaSlotList); + pk11_FreeSlotListStatic(&pk11_sslSlotList); + pk11_FreeSlotListStatic(&pk11_tlsSlotList); + pk11_FreeSlotListStatic(&pk11_randomSlotList); + pk11_FreeSlotListStatic(&pk11_sha256SlotList); + pk11_FreeSlotListStatic(&pk11_sha512SlotList); return; } @@ -955,7 +971,7 @@ PK11_ClearSlotList(PK11SlotInfo *slot) if (le) { PK11_DeleteSlotFromList(slotList,le); - pk11_FreeListElement(slotList,le); + PK11_FreeSlotListElement(slotList,le); } } } @@ -2065,7 +2081,7 @@ PK11_GetBestSlotMultiple(CK_MECHANISM_TYPE *type, int mech_count, void *wincx) } slot = le->slot; PK11_ReferenceSlot(slot); - pk11_FreeListElement(list,le); + PK11_FreeSlotListElement(list,le); if (freeit) { PK11_FreeSlotList(list); } return slot; } @@ -2106,9 +2122,29 @@ PK11_SeedRandom(PK11SlotInfo *slot, unsigned char *data, int len) { CK_RV crv; PK11_EnterSlotMonitor(slot); - crv = PK11_GETTAB(slot)->C_SeedRandom(slot->session,data, (CK_ULONG)len); + crv = PK11_GETTAB(slot)->C_SeedRandom(slot->session, data, (CK_ULONG)len); PK11_ExitSlotMonitor(slot); - return (crv != CKR_OK) ? SECFailure : SECSuccess; + if (crv != CKR_OK) { + PORT_SetError(PK11_MapError(crv)); + return SECFailure; + } + return SECSuccess; +} + + +SECStatus +PK11_GenerateRandomOnSlot(PK11SlotInfo *slot, unsigned char *data, int len) { + CK_RV crv; + + if (!slot->isInternal) PK11_EnterSlotMonitor(slot); + crv = PK11_GETTAB(slot)->C_GenerateRandom(slot->session,data, + (CK_ULONG)len); + if (!slot->isInternal) PK11_ExitSlotMonitor(slot); + if (crv != CKR_OK) { + PORT_SetError(PK11_MapError(crv)); + return SECFailure; + } + return SECSuccess; } /* Attempts to update the Best Slot for "FAKE RANDOM" generation. @@ -2147,17 +2183,14 @@ PK11_RandomUpdate(void *data, size_t bytes) SECStatus PK11_GenerateRandom(unsigned char *data,int len) { PK11SlotInfo *slot; - CK_RV crv; + SECStatus rv; slot = PK11_GetBestSlot(CKM_FAKE_RANDOM,NULL); if (slot == NULL) return SECFailure; - if (!slot->isInternal) PK11_EnterSlotMonitor(slot); - crv = PK11_GETTAB(slot)->C_GenerateRandom(slot->session,data, - (CK_ULONG)len); - if (!slot->isInternal) PK11_ExitSlotMonitor(slot); + rv = PK11_GenerateRandomOnSlot(slot, data, len); PK11_FreeSlot(slot); - return (crv != CKR_OK) ? SECFailure : SECSuccess; + return rv; } /* diff --git a/security/nss/lib/pk11wrap/pk11util.c b/security/nss/lib/pk11wrap/pk11util.c index 5c6998da8..e4edaf2e6 100644 --- a/security/nss/lib/pk11wrap/pk11util.c +++ b/security/nss/lib/pk11wrap/pk11util.c @@ -45,6 +45,7 @@ #include "pki3hack.h" #include "secerr.h" #include "dev.h" +#include "pkcs11ni.h" /* these are for displaying error messages */ @@ -859,9 +860,9 @@ SECMOD_UpdateSlotList(SECMODModule *mod) { CK_RV crv; CK_ULONG count; - int i, oldCount; + CK_ULONG i, oldCount; PRBool freeRef = PR_FALSE; - void *mark; + void *mark = NULL; CK_ULONG *slotIDs = NULL; PK11SlotInfo **newSlots = NULL; PK11SlotInfo **oldSlots = NULL; @@ -882,7 +883,7 @@ SECMOD_UpdateSlotList(SECMODModule *mod) PZ_Unlock(mod->refLock); return SECSuccess; } - if (count < mod->slotCount) { + if (count < (CK_ULONG)mod->slotCount) { /* shouldn't happen with a properly functioning PKCS #11 module */ PORT_SetError( SEC_ERROR_INCOMPATIBLE_PKCS11 ); goto loser; @@ -1060,13 +1061,15 @@ SECMOD_WaitForAnyTokenEvent(SECMODModule *mod, unsigned long flags, CK_RV crv; PK11SlotInfo *slot; - if ((mod->cryptokiVersion.major == 2) && - (mod->cryptokiVersion.minor < 1)) { - /* if the module is version 2.0, - * C_WaitForSlotEvent() doesn't exist */ + if (!pk11_getFinalizeModulesOption() || + ((mod->cryptokiVersion.major == 2) && + (mod->cryptokiVersion.minor < 1))) { + /* if we are sharing the module with other software in our + * address space, we can't reliably use C_WaitForSlotEvent(), + * and if the module is version 2.0, C_WaitForSlotEvent() doesn't + * exist */ return secmod_HandleWaitForSlotEvent(mod, flags, latency); } - /* first the the PKCS #11 call */ PZ_Lock(mod->refLock); if (mod->evControlMask & SECMOD_END_WAIT) { @@ -1137,16 +1140,24 @@ SECMOD_CancelWait(SECMODModule *mod) mod->evControlMask |= SECMOD_END_WAIT; controlMask = mod->evControlMask; if (controlMask & SECMOD_WAIT_PKCS11_EVENT) { + if (!pk11_getFinalizeModulesOption()) { + /* can't get here unless pk11_getFinalizeModulesOption is set */ + PORT_Assert(0); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + rv = SECFailure; + goto loser; + } /* NOTE: this call will drop all transient keys, in progress * operations, and any authentication. This is the only documented * way to get WaitForSlotEvent to return. Also note: for non-thread * safe tokens, we need to hold the module lock, this is not yet at - * system shutdown/starup time, so we need to protect these calls */ + * system shutdown/startup time, so we need to protect these calls */ crv = PK11_GETTAB(mod)->C_Finalize(NULL); /* ok, we slammed the module down, now we need to reinit it in case * we intend to use it again */ if (CKR_OK == crv) { - secmod_ModuleInit(mod); + PRBool alreadyLoaded; + secmod_ModuleInit(mod, &alreadyLoaded); } else { /* Finalized failed for some reason, notify the application * so maybe it has a prayer of recovering... */ @@ -1158,6 +1169,7 @@ SECMOD_CancelWait(SECMODModule *mod) /* Simulated events will eventually timeout * and wake up in the loop */ } +loser: PZ_Unlock(mod->refLock); return rv; } @@ -1185,3 +1197,244 @@ SECMOD_HasRemovableSlots(SECMODModule *mod) SECMOD_ReleaseReadLock(moduleLock); return ret; } + +/* + * helper function to actually create and destroy user defined slots + */ +static SECStatus +secmod_UserDBOp(CK_OBJECT_CLASS objClass, const char *sendSpec) +{ + PK11SlotInfo *slot = PK11_GetInternalSlot(); + CK_OBJECT_HANDLE dummy; + CK_ATTRIBUTE template[2] ; + CK_ATTRIBUTE *attrs = template; + SECStatus rv; + CK_RV crv; + + PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass)); attrs++; + PK11_SETATTRS(attrs, CKA_NETSCAPE_MODULE_SPEC , (unsigned char *)sendSpec, + strlen(sendSpec)+1); attrs++; + + PORT_Assert(attrs-template <= 2); + + + PK11_EnterSlotMonitor(slot); + crv = PK11_CreateNewObject(slot, slot->session, + template, attrs-template, PR_FALSE, &dummy); + PK11_ExitSlotMonitor(slot); + + if (crv != CKR_OK) { + PK11_FreeSlot(slot); + PORT_SetError(PK11_MapError(crv)); + return SECFailure; + } + rv = SECMOD_UpdateSlotList(slot->module); + PK11_FreeSlot(slot); + return rv; +} + +/* + * add escapes to protect quote characters... + */ +static char * +nss_addEscape(const char *string, char quote) +{ + char *newString = 0; + int escapes = 0, size = 0; + const char *src; + char *dest; + + for (src=string; *src ; src++) { + if ((*src == quote) || (*src == '\\')) escapes++; + size++; + } + + newString = PORT_ZAlloc(escapes+size+1); + if (newString == NULL) { + return NULL; + } + + for (src=string, dest=newString; *src; src++,dest++) { + if ((*src == '\\') || (*src == quote)) { + *dest++ = '\\'; + } + *dest = *src; + } + + return newString; +} + +static char * +nss_doubleEscape(const char *string) +{ + char *round1 = NULL; + char *retValue = NULL; + if (string == NULL) { + goto done; + } + round1 = nss_addEscape(string,'>'); + if (round1) { + retValue = nss_addEscape(round1,']'); + PORT_Free(round1); + } + +done: + if (retValue == NULL) { + retValue = PORT_Strdup(""); + } + return retValue; +} + +/* + * Open a new database using the softoken. The caller is responsible for making + * sure the module spec is correct and usable. The caller should ask for one + * new database per call if the caller wants to get meaningful information + * about the new database. + * + * moduleSpec is the same data that you would pass to softoken at + * initialization time under the 'tokens' options. For example, if you were + * to specify tokens=<0x4=[configdir='./mybackup' tokenDescription='Backup']> + * You would specify "configdir='./mybackup' tokenDescription='Backup'" as your + * module spec here. The slot ID will be calculated for you by + * SECMOD_OpenUserDB(). + * + * Typical parameters here are configdir, tokenDescription and flags. + * + * a Full list is below: + * + * + * configDir - The location of the databases for this token. If configDir is + * not specified, and noCertDB and noKeyDB is not specified, the load + * will fail. + * certPrefix - Cert prefix for this token. + * keyPrefix - Prefix for the key database for this token. (if not specified, + * certPrefix will be used). + * tokenDescription - The label value for this token returned in the + * CK_TOKEN_INFO structure with an internationalize string (UTF8). + * This value will be truncated at 32 bytes (no NULL, partial UTF8 + * characters dropped). You should specify a user friendly name here + * as this is the value the token will be refered to in most + * application UI's. You should make sure tokenDescription is unique. + * slotDescription - The slotDescription value for this token returned + * in the CK_SLOT_INFO structure with an internationalize string + * (UTF8). This value will be truncated at 64 bytes (no NULL, partial + * UTF8 characters dropped). This name will not change after the + * database is closed. It should have some number to make this unique. + * minPWLen - minimum password length for this token. + * flags - comma separated list of flag values, parsed case-insensitive. + * Valid flags are: + * readOnly - Databases should be opened read only. + * noCertDB - Don't try to open a certificate database. + * noKeyDB - Don't try to open a key database. + * forceOpen - Don't fail to initialize the token if the + * databases could not be opened. + * passwordRequired - zero length passwords are not acceptable + * (valid only if there is a keyDB). + * optimizeSpace - allocate smaller hash tables and lock tables. + * When this flag is not specified, Softoken will allocate + * large tables to prevent lock contention. + */ +PK11SlotInfo * +SECMOD_OpenUserDB(const char *moduleSpec) +{ + CK_SLOT_ID slotID = 0; + char *escSpec; + char *sendSpec; + SECStatus rv; + SECMODModule *mod; + CK_SLOT_ID i, minSlotID, maxSlotID; + PRBool found = PR_FALSE; + + if (moduleSpec == NULL) { + return NULL; + } + + /* NOTE: unlike most PK11 function, this does not return a reference + * to the module */ + mod = SECMOD_GetInternalModule(); + if (!mod) { + /* shouldn't happen */ + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return NULL; + } + + /* look for a free slot id on the internal module */ + if (mod->isFIPS) { + minSlotID = SFTK_MIN_FIPS_USER_SLOT_ID; + maxSlotID = SFTK_MAX_FIPS_USER_SLOT_ID; + } else { + minSlotID = SFTK_MIN_USER_SLOT_ID; + maxSlotID = SFTK_MAX_USER_SLOT_ID; + } + for (i=minSlotID; i < maxSlotID; i++) { + PK11SlotInfo *slot = SECMOD_LookupSlot(mod->moduleID, i); + if (slot) { + PRBool present = PK11_IsPresent(slot); + PK11_FreeSlot(slot); + if (present) { + continue; + } + /* not present means it's available */ + } + /* it doesn't exist or isn't present, it's available */ + slotID = i; + found = PR_TRUE; + break; + } + + if (!found) { + /* this could happen if we try to open too many slots */ + PORT_SetError(SEC_ERROR_NO_SLOT_SELECTED); + return NULL; + } + + /* we've found the slot, now build the moduleSpec */ + + escSpec = nss_doubleEscape(moduleSpec); + if (escSpec == NULL) { + return NULL; + } + sendSpec = PR_smprintf("tokens=[0x%x=<%s>]", slotID, escSpec); + PORT_Free(escSpec); + + if (sendSpec == NULL) { + /* PR_smprintf does not set no memory error */ + PORT_SetError(SEC_ERROR_NO_MEMORY); + return NULL; + } + rv = secmod_UserDBOp(CKO_NETSCAPE_NEWSLOT, sendSpec); + PR_smprintf_free(sendSpec); + if (rv != SECSuccess) { + return NULL; + } + + return SECMOD_FindSlotByID(mod, slotID); +} + +/* + * close an already opened user database. NOTE: the database must be + * in the internal token, and must be one created with SECMOD_OpenUserDB(). + * Once the database is closed, the slot will remain as an empty slot + * until it's used again with SECMOD_OpenUserDB(). + */ +SECStatus +SECMOD_CloseUserDB(PK11SlotInfo *slot) +{ + SECStatus rv; + char *sendSpec; + + if (!slot->isInternal) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + sendSpec = PR_smprintf("tokens=[0x%x=<>]", slot->slotID); + if (sendSpec == NULL) { + /* PR_smprintf does not set no memory error */ + PORT_SetError(SEC_ERROR_NO_MEMORY); + return SECFailure; + } + rv = secmod_UserDBOp(CKO_NETSCAPE_DELSLOT, sendSpec); + PR_smprintf_free(sendSpec); + return rv; +} diff --git a/security/nss/lib/pk11wrap/secmodi.h b/security/nss/lib/pk11wrap/secmodi.h index 4514cdaf5..1e3a6aebd 100644 --- a/security/nss/lib/pk11wrap/secmodi.h +++ b/security/nss/lib/pk11wrap/secmodi.h @@ -59,7 +59,7 @@ void nss_DumpModuleLog(void); extern int secmod_PrivateModuleCount; extern void SECMOD_Init(void); -SECStatus secmod_ModuleInit(SECMODModule *mod); +SECStatus secmod_ModuleInit(SECMODModule *mod, PRBool* alreadyLoaded); /* list managment */ extern SECStatus SECMOD_AddModuleToList(SECMODModule *newModule); @@ -135,7 +135,6 @@ unsigned int pk11_AttrFlagsToAttributes(PK11AttrFlags attrFlags, PRBool pk11_FindAttrInTemplate(CK_ATTRIBUTE *attr, unsigned int numAttrs, CK_ATTRIBUTE_TYPE target); -CK_MECHANISM_TYPE pk11_mapSignKeyType(KeyType keyType); CK_MECHANISM_TYPE pk11_mapWrapKeyType(KeyType keyType); PK11SymKey *pk11_KeyExchange(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation, CK_FLAGS flags, PRBool isPerm, diff --git a/security/nss/lib/pk11wrap/secmodt.h b/security/nss/lib/pk11wrap/secmodt.h index cc63eddc7..a6f7b180f 100644 --- a/security/nss/lib/pk11wrap/secmodt.h +++ b/security/nss/lib/pk11wrap/secmodt.h @@ -66,6 +66,7 @@ typedef struct PK11RSAGenParamsStr PK11RSAGenParams; typedef unsigned long SECMODModuleID; typedef struct PK11DefaultArrayEntryStr PK11DefaultArrayEntry; typedef struct PK11GenericObjectStr PK11GenericObject; +typedef void (*PK11FreeDataFunc)(void *); struct SECMODModuleStr { PRArenaPool *arena; diff --git a/security/nss/lib/pk11wrap/secmodti.h b/security/nss/lib/pk11wrap/secmodti.h index a338e7b6d..328a07130 100644 --- a/security/nss/lib/pk11wrap/secmodti.h +++ b/security/nss/lib/pk11wrap/secmodti.h @@ -97,6 +97,7 @@ struct PK11SlotInfoStr { * still in use */ PRInt32 refCount; /* to be in/decremented by atomic calls ONLY! */ PZLock *freeListLock; + PK11SymKey *freeSymKeysWithSessionHead; PK11SymKey *freeSymKeysHead; int keyCount; int maxKeyCount; @@ -153,19 +154,22 @@ struct PK11SymKeyStr { CK_OBJECT_HANDLE objectID; /* object id of this key in the slot */ PK11SlotInfo *slot; /* Slot this key is loaded into */ void *cx; /* window context in case we need to loggin */ - PK11SymKey *next; - PRBool owner; - SECItem data; /* raw key data if available */ + PK11SymKey *next; + PRBool owner; + SECItem data; /* raw key data if available */ CK_SESSION_HANDLE session; - PRBool sessionOwner; - PRInt32 refCount; /* number of references to this key */ - int size; /* key size in bytes */ - PK11Origin origin; /* where this key came from - (see def in secmodt.h) */ - PK11SymKey *parent; - uint16 series; /* break up the slot info into various groups of - * inserted tokens so that keys and certs can be - * invalidated */ + PRBool sessionOwner; + PRInt32 refCount; /* number of references to this key */ + int size; /* key size in bytes */ + PK11Origin origin; /* where this key came from + * (see def in secmodt.h) */ + PK11SymKey *parent; /* potential owner key of the session */ + uint16 series; /* break up the slot info into various groups + * of inserted tokens so that keys and certs + * can be invalidated */ + void *userData; /* random data the application can attach to + * this key */ + PK11FreeDataFunc freeFunc; /* function to free the user data */ }; diff --git a/security/nss/lib/pkcs12/manifest.mn b/security/nss/lib/pkcs12/manifest.mn index 7812674f2..af76ca2ed 100644 --- a/security/nss/lib/pkcs12/manifest.mn +++ b/security/nss/lib/pkcs12/manifest.mn @@ -59,8 +59,4 @@ CSRCS = \ REQUIRES = dbm -ifdef NSS_ENABLE_ECC -DEFINES += -DNSS_ENABLE_ECC -endif - LIBRARY_NAME = pkcs12 diff --git a/security/nss/lib/pkcs12/p12d.c b/security/nss/lib/pkcs12/p12d.c index dd96e99bd..2d4d29cae 100644 --- a/security/nss/lib/pkcs12/p12d.c +++ b/security/nss/lib/pkcs12/p12d.c @@ -110,7 +110,6 @@ struct SEC_PKCS12DecoderContextStr { /* state variables for decoding authenticated safes. */ SEC_PKCS7DecoderContext *currentASafeP7Dcx; - SEC_PKCS5KeyAndPassword *currentASafeKeyPwd; SEC_ASN1DecoderContext *aSafeDcx; SEC_PKCS7DecoderContext *aSafeP7Dcx; sec_PKCS12AuthenticatedSafe authSafe; @@ -173,25 +172,43 @@ sec_pkcs12_proper_version(sec_PKCS12PFXItem *pfx) static PK11SymKey * sec_pkcs12_decoder_get_decrypt_key(void *arg, SECAlgorithmID *algid) { - SEC_PKCS5KeyAndPassword *keyPwd = - (SEC_PKCS5KeyAndPassword *)arg; + SEC_PKCS12DecoderContext *p12dcx = + (SEC_PKCS12DecoderContext *) arg; + PK11SlotInfo *slot; + PK11SymKey *bulkKey; - if(!keyPwd) { + if(!p12dcx) { return NULL; } /* if no slot specified, use the internal key slot */ - if(!keyPwd->slot) { - keyPwd->slot = PK11_GetInternalKeySlot(); + if(p12dcx->slot) { + slot = PK11_ReferenceSlot(p12dcx->slot); + } else { + slot = PK11_GetInternalKeySlot(); + } + + bulkKey = PK11_PBEKeyGen(slot, algid, p12dcx->pwitem, + PR_FALSE, p12dcx->wincx); + /* some tokens can't generate PBE keys on their own, generate the + * key in the internal slot, and let the Import code deal with it, + * (if the slot can't generate PBEs, then we need to use the internal + * slot anyway to unwrap). */ + if (!bulkKey && !PK11_IsInternal(slot)) { + PK11_FreeSlot(slot); + slot = PK11_GetInternalKeySlot(); + bulkKey = PK11_PBEKeyGen(slot, algid, p12dcx->pwitem, + PR_FALSE, p12dcx->wincx); } + PK11_FreeSlot(slot); - /* retrieve the key */ - if(!keyPwd->key) { - keyPwd->key = PK11_PBEKeyGen(keyPwd->slot, algid, - keyPwd->pwitem, PR_FALSE, keyPwd->wincx); + /* set the password data on the key */ + if (bulkKey) { + PK11_SetSymKeyUserData(bulkKey,p12dcx->pwitem, NULL); } - return (PK11SymKey *)keyPwd; + + return bulkKey; } /* XXX this needs to be modified to handle enveloped data. most @@ -778,25 +795,12 @@ sec_pkcs12_decoder_asafes_notify(void *arg, PRBool before, void *dest, goto loser; } - /* set up password and encryption key information */ - p12dcx->currentASafeKeyPwd = - (SEC_PKCS5KeyAndPassword*)PORT_ArenaZAlloc(p12dcx->arena, - sizeof(SEC_PKCS5KeyAndPassword)); - if(!p12dcx->currentASafeKeyPwd) { - p12dcx->errorValue = SEC_ERROR_NO_MEMORY; - goto loser; - } - p12dcx->currentASafeKeyPwd->pwitem = p12dcx->pwitem; - p12dcx->currentASafeKeyPwd->slot = p12dcx->slot; - p12dcx->currentASafeKeyPwd->wincx = p12dcx->wincx; - /* initiate the PKCS7ContentInfo decode */ p12dcx->currentASafeP7Dcx = SEC_PKCS7DecoderStart( sec_pkcs12_decoder_safe_contents_callback, safeContentsCtx, p12dcx->pwfn, p12dcx->pwfnarg, - sec_pkcs12_decoder_get_decrypt_key, - p12dcx->currentASafeKeyPwd, + sec_pkcs12_decoder_get_decrypt_key, p12dcx, sec_pkcs12_decoder_decryption_allowed); if(!p12dcx->currentASafeP7Dcx) { p12dcx->errorValue = PORT_GetError(); @@ -818,9 +822,6 @@ sec_pkcs12_decoder_asafes_notify(void *arg, PRBool before, void *dest, p12dcx->currentASafeP7Dcx = NULL; } p12dcx->currentASafeP7Dcx = NULL; - if(p12dcx->currentASafeKeyPwd->key != NULL) { - p12dcx->currentASafeKeyPwd->key = NULL; - } } @@ -2793,11 +2794,9 @@ sec_pkcs12_get_public_value_and_type(sec_PKCS12SafeBag *certBag, case rsaKey: pubValue = SECITEM_DupItem(&pubKey->u.rsa.modulus); break; -#ifdef NSS_ENABLE_ECC case ecKey: pubValue = SECITEM_DupItem(&pubKey->u.ec.publicValue); break; -#endif /* NSS_ENABLE_ECC */ default: pubValue = NULL; } diff --git a/security/nss/lib/pkcs12/p12e.c b/security/nss/lib/pkcs12/p12e.c index 650fd175c..f0fbbcb2e 100644 --- a/security/nss/lib/pkcs12/p12e.c +++ b/security/nss/lib/pkcs12/p12e.c @@ -1901,10 +1901,9 @@ sec_pkcs12_encoder_asafe_process(sec_PKCS12EncoderContext *p12ecx) { SEC_PKCS7EncoderContext *innerP7ecx; SEC_PKCS7ContentInfo *cinfo; - void *arg = NULL; + PK11SymKey *bulkKey = NULL; SEC_ASN1EncoderContext *innerA1ecx = NULL; SECStatus rv = SECSuccess; - SEC_PKCS5KeyAndPassword keyPwd; if(p12ecx->currentSafe < p12ecx->p12exp->authSafe.safeCount) { SEC_PKCS12SafeInfo *safeInfo; @@ -1923,15 +1922,11 @@ sec_pkcs12_encoder_asafe_process(sec_PKCS12EncoderContext *p12ecx) /* determine the safe type and set the appropriate argument */ switch(cinfoType) { case SEC_OID_PKCS7_DATA: - arg = NULL; + case SEC_OID_PKCS7_ENVELOPED_DATA: break; case SEC_OID_PKCS7_ENCRYPTED_DATA: - keyPwd.pwitem = &safeInfo->pwitem; - keyPwd.key = safeInfo->encryptionKey; - arg = &keyPwd; - break; - case SEC_OID_PKCS7_ENVELOPED_DATA: - arg = NULL; + bulkKey = safeInfo->encryptionKey; + PK11_SetSymKeyUserData(bulkKey, &safeInfo->pwitem, NULL); break; default: return SECFailure; @@ -1941,7 +1936,7 @@ sec_pkcs12_encoder_asafe_process(sec_PKCS12EncoderContext *p12ecx) /* start the PKCS7 encoder */ innerP7ecx = SEC_PKCS7EncoderStart(cinfo, sec_P12P7OutputCB_CallA1Update, - p12ecx->middleA1ecx, (PK11SymKey *)arg); + p12ecx->middleA1ecx, bulkKey); if(!innerP7ecx) { goto loser; } diff --git a/security/nss/lib/pkcs7/p7decode.c b/security/nss/lib/pkcs7/p7decode.c index 36f4d6945..37a0c5b40 100644 --- a/security/nss/lib/pkcs7/p7decode.c +++ b/security/nss/lib/pkcs7/p7decode.c @@ -19,6 +19,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -690,16 +691,6 @@ sec_pkcs7_decoder_start_decrypt (SEC_PKCS7DecoderContext *p7dcx, int depth, decryptobj = sec_PKCS7CreateDecryptObject (bulkkey, &(enccinfo->contentEncAlg)); - /* - * For PKCS5 Encryption Algorithms, the bulkkey is actually a different - * structure. Therefore, we need to set the bulkkey to the actual key - * prior to freeing it. - */ - if ( SEC_PKCS5IsAlgorithmPBEAlg(&(enccinfo->contentEncAlg)) && bulkkey ) { - SEC_PKCS5KeyAndPassword *keyPwd = (SEC_PKCS5KeyAndPassword *)bulkkey; - bulkkey = keyPwd->key; - } - /* * We are done with (this) bulkkey now. */ @@ -1674,6 +1665,7 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo, algiddata = SECOID_FindOID (&(signerinfo->digestEncAlg.algorithm)); if (algiddata == NULL || ((algiddata->offset != SEC_OID_PKCS1_RSA_ENCRYPTION) && + (algiddata->offset != SEC_OID_ANSIX962_EC_PUBLIC_KEY) && (algiddata->offset != SEC_OID_ANSIX9_DSA_SIGNATURE))) { PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE); goto done; @@ -1743,6 +1735,10 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo, goto done; } + /* + * XXX the 5th (algid) argument should be the signature algorithm. + * See sec_pkcs7_pick_sign_alg in p7encode.c. + */ goodsig = (PRBool)(VFY_VerifyData (encoded_attrs.data, encoded_attrs.len, publickey, &(signerinfo->encDigest), @@ -1801,6 +1797,10 @@ sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo, sig = &holder; } + /* + * XXX the 4th (algid) argument should be the signature algorithm. + * See sec_pkcs7_pick_sign_alg in p7encode.c. + */ goodsig = (PRBool)(VFY_VerifyDigest (digest, publickey, sig, SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg)), cinfo->pwfn_arg) diff --git a/security/nss/lib/pkcs7/p7encode.c b/security/nss/lib/pkcs7/p7encode.c index 3188e0d21..2ef105598 100644 --- a/security/nss/lib/pkcs7/p7encode.c +++ b/security/nss/lib/pkcs7/p7encode.c @@ -19,6 +19,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -869,6 +870,13 @@ sec_pkcs7_pick_sign_alg (SECOidTag hashalg, SECOidTag encalg) default: return SEC_OID_UNKNOWN; } + case SEC_OID_ANSIX962_EC_PUBLIC_KEY: + switch (hashalg) { + case SEC_OID_SHA1: + return SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST; + default: + return SEC_OID_UNKNOWN; + } default: break; } diff --git a/security/nss/lib/pkcs7/p7local.c b/security/nss/lib/pkcs7/p7local.c index c75182282..b7f79b696 100644 --- a/security/nss/lib/pkcs7/p7local.c +++ b/security/nss/lib/pkcs7/p7local.c @@ -118,11 +118,12 @@ sec_PKCS7CreateDecryptObject (PK11SymKey *key, SECAlgorithmID *algid) if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { CK_MECHANISM pbeMech, cryptoMech; SECItem *pbeParams, *pwitem; - SEC_PKCS5KeyAndPassword *keyPwd; - keyPwd = (SEC_PKCS5KeyAndPassword *)key; - key = keyPwd->key; - pwitem = keyPwd->pwitem; + pwitem = (SECItem *)PK11_GetSymKeyUserData(key); + if (!pwitem) { + PORT_Free(result); + return NULL; + } pbeMech.mechanism = PK11_AlgtagToMechanism(algtag); pbeParams = PK11_ParamFromAlgid(algid); @@ -211,25 +212,28 @@ sec_PKCS7CreateEncryptObject (PRArenaPool *poolp, PK11SymKey *key, ciphercx = NULL; if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { CK_MECHANISM pbeMech, cryptoMech; - SECItem *pbeParams; - SEC_PKCS5KeyAndPassword *keyPwd; + SECItem *pbeParams, *pwitem; PORT_Memset(&pbeMech, 0, sizeof(CK_MECHANISM)); PORT_Memset(&cryptoMech, 0, sizeof(CK_MECHANISM)); + pwitem = (SECItem *)PK11_GetSymKeyUserData(key); + if (!pwitem) { + PORT_Free(result); + return NULL; + } + pbeMech.mechanism = PK11_AlgtagToMechanism(algtag); pbeParams = PK11_ParamFromAlgid(algid); if(!pbeParams) { PORT_Free(result); return NULL; } - keyPwd = (SEC_PKCS5KeyAndPassword *)key; - key = keyPwd->key; pbeMech.pParameter = pbeParams->data; pbeMech.ulParameterLen = pbeParams->len; - if(PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, - keyPwd->pwitem, PR_FALSE) != CKR_OK) { + if(PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, pwitem, + PR_FALSE) != CKR_OK) { PORT_Free(result); SECITEM_ZfreeItem(pbeParams, PR_TRUE); return NULL; diff --git a/security/nss/lib/pki/certificate.c b/security/nss/lib/pki/certificate.c index f82b090da..3abca38c1 100644 --- a/security/nss/lib/pki/certificate.c +++ b/security/nss/lib/pki/certificate.c @@ -481,7 +481,7 @@ nssCertificate_BuildChain ( { NSSCertificate **rvChain = NULL; NSSUsage issuerUsage = *usage; - nssPKIObjectCollection *collection; + nssPKIObjectCollection *collection = NULL; PRUint32 rvCount = 0; PRStatus st; PRStatus ret = PR_SUCCESS; @@ -767,6 +767,26 @@ NSSCertificate_IsPrivateKeyAvailable ( return isUser; } +/* sort the subject cert list from newest to oldest */ +PRIntn +nssCertificate_SubjectListSort ( + void *v1, + void *v2 +) +{ + NSSCertificate *c1 = (NSSCertificate *)v1; + NSSCertificate *c2 = (NSSCertificate *)v2; + nssDecodedCert *dc1 = nssCertificate_GetDecoding(c1); + nssDecodedCert *dc2 = nssCertificate_GetDecoding(c2); + if (!dc1) { + return dc2 ? 1 : 0; + } else if (!dc2) { + return -1; + } else { + return dc1->isNewerThan(dc1, dc2) ? -1 : 1; + } +} + NSS_IMPLEMENT PRBool NSSUserCertificate_IsStillPresent ( NSSUserCertificate *uc, @@ -860,83 +880,6 @@ NSSUserCertificate_DeriveSymmetricKey ( return NULL; } -NSS_IMPLEMENT void -nssBestCertificate_SetArgs ( - nssBestCertificateCB *best, - NSSTime *timeOpt, - NSSUsage *usage, - NSSPolicies *policies -) -{ - if (timeOpt) { - best->time = timeOpt; - } else { - NSSTime_Now(&best->sTime); - best->time = &best->sTime; - } - best->usage = usage; - best->policies = policies; - best->cert = NULL; -} - -NSS_IMPLEMENT PRStatus -nssBestCertificate_Callback ( - NSSCertificate *c, - void *arg -) -{ - nssBestCertificateCB *best = (nssBestCertificateCB *)arg; - nssDecodedCert *dc, *bestdc; - dc = nssCertificate_GetDecoding(c); - if (!best->cert) { - /* usage */ - if (best->usage->anyUsage) { - best->cert = nssCertificate_AddRef(c); - } else { -#ifdef NSS_3_4_CODE - /* For this to work in NSS 3.4, we have to go out and fill in - * all of the CERTCertificate fields. Why? Because the - * matchUsage function calls CERT_IsCACert, which needs to know - * what the trust values are for the cert. - * Ignore the returned pointer, the refcount is in c anyway. - */ - if (STAN_GetCERTCertificate(c) == NULL) { - return PR_FAILURE; - } -#endif - if (dc->matchUsage(dc, best->usage)) { - best->cert = nssCertificate_AddRef(c); - } - } - return PR_SUCCESS; - } - bestdc = nssCertificate_GetDecoding(best->cert); - /* time */ - if (bestdc->isValidAtTime(bestdc, best->time)) { - /* The current best cert is valid at time */ - if (!dc->isValidAtTime(dc, best->time)) { - /* If the new cert isn't valid at time, it's not better */ - return PR_SUCCESS; - } - } else { - /* The current best cert is not valid at time */ - if (dc->isValidAtTime(dc, best->time)) { - /* If the new cert is valid at time, it's better */ - NSSCertificate_Destroy(best->cert); - best->cert = nssCertificate_AddRef(c); - return PR_SUCCESS; - } - } - /* either they are both valid at time, or neither valid; take the newer */ - /* XXX later -- defer to policies */ - if (!bestdc->isNewerThan(bestdc, dc)) { - NSSCertificate_Destroy(best->cert); - best->cert = nssCertificate_AddRef(c); - } - /* policies */ - return PR_SUCCESS; -} - NSS_IMPLEMENT nssSMIMEProfile * nssSMIMEProfile_Create ( NSSCertificate *cert, diff --git a/security/nss/lib/pki/pkim.h b/security/nss/lib/pki/pkim.h index 3a28335d6..5fad8a13f 100644 --- a/security/nss/lib/pki/pkim.h +++ b/security/nss/lib/pki/pkim.h @@ -233,6 +233,13 @@ nssCertificate_GetDecoding NSSCertificate *c ); +extern PRIntn +nssCertificate_SubjectListSort +( + void *v1, + void *v2 +); + NSS_EXTERN nssDecodedCert * nssDecodedCert_Create ( diff --git a/security/nss/lib/pki/pkistore.c b/security/nss/lib/pki/pkistore.c index d069846cf..ed35c9749 100644 --- a/security/nss/lib/pki/pkistore.c +++ b/security/nss/lib/pki/pkistore.c @@ -89,25 +89,6 @@ struct certificate_hash_entry_str nssSMIMEProfile *profile; }; -/* XXX This a common function that should be moved out, possibly an - * nssSubjectCertificateList should be created? - */ -/* sort the subject list from newest to oldest */ -static PRIntn subject_list_sort(void *v1, void *v2) -{ - NSSCertificate *c1 = (NSSCertificate *)v1; - NSSCertificate *c2 = (NSSCertificate *)v2; - nssDecodedCert *dc1 = nssCertificate_GetDecoding(c1); - nssDecodedCert *dc2 = nssCertificate_GetDecoding(c2); - if (!dc1) { - return dc2 ? 1 : 0; - } else if (!dc2) { - return -1; - } else { - return dc1->isNewerThan(dc1, dc2) ? -1 : 1; - } -} - NSS_IMPLEMENT nssCertificateStore * nssCertificateStore_Create ( NSSArena *arenaOpt @@ -225,7 +206,7 @@ add_subject_entry ( if (!subjectList) { return PR_FAILURE; } - nssList_SetSortFunction(subjectList, subject_list_sort); + nssList_SetSortFunction(subjectList, nssCertificate_SubjectListSort); /* Add the cert entry to this list of subjects */ nssrv = nssList_Add(subjectList, cert); if (nssrv != PR_SUCCESS) { diff --git a/security/nss/lib/pki/pkitm.h b/security/nss/lib/pki/pkitm.h index 04d701c45..7530809de 100644 --- a/security/nss/lib/pki/pkitm.h +++ b/security/nss/lib/pki/pkitm.h @@ -105,16 +105,6 @@ struct NSSUsageStr { #endif }; -typedef struct nssBestCertificateCBStr nssBestCertificateCB; - -struct nssBestCertificateCBStr { - NSSCertificate *cert; - NSSTime *time; - NSSTime sTime; /* to avoid allocating when unnecessary */ - NSSUsage *usage; - NSSPolicies *policies; -}; - typedef struct nssPKIObjectCollectionStr nssPKIObjectCollection; typedef struct diff --git a/security/nss/lib/pki/tdcache.c b/security/nss/lib/pki/tdcache.c index b85e88143..90727d011 100644 --- a/security/nss/lib/pki/tdcache.c +++ b/security/nss/lib/pki/tdcache.c @@ -150,22 +150,6 @@ new_cache_entry(NSSArena *arena, void *value, PRBool ownArena) return ce; } -/* sort the subject list from newest to oldest */ -static PRIntn subject_list_sort(void *v1, void *v2) -{ - NSSCertificate *c1 = (NSSCertificate *)v1; - NSSCertificate *c2 = (NSSCertificate *)v2; - nssDecodedCert *dc1 = nssCertificate_GetDecoding(c1); - nssDecodedCert *dc2 = nssCertificate_GetDecoding(c2); - if (!dc1) { - return dc2 ? 1 : 0; - } else if (!dc2) { - return -1; - } else { - return dc1->isNewerThan(dc1, dc2) ? -1 : 1; - } -} - /* this should not be exposed in a header, but is here to keep the above * types/functions static */ @@ -598,7 +582,7 @@ add_subject_entry ( if (nickname) { ce->nickname = nssUTF8_Duplicate(nickname, arena); } - nssList_SetSortFunction(list, subject_list_sort); + nssList_SetSortFunction(list, nssCertificate_SubjectListSort); /* Add the cert entry to this list of subjects */ nssrv = nssList_AddUnique(list, cert); if (nssrv != PR_SUCCESS) { diff --git a/security/nss/lib/smime/cmscipher.c b/security/nss/lib/smime/cmscipher.c index c4a37208f..00042937a 100644 --- a/security/nss/lib/smime/cmscipher.c +++ b/security/nss/lib/smime/cmscipher.c @@ -93,17 +93,14 @@ NSS_CMSCipherContext_StartDecrypt(PK11SymKey *key, SECAlgorithmID *algid) /* set param and mechanism */ if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { CK_MECHANISM pbeMech, cryptoMech; - SECItem *pbeParams; - SEC_PKCS5KeyAndPassword *keyPwd; + SECItem *pbeParams, *pwitem; PORT_Memset(&pbeMech, 0, sizeof(CK_MECHANISM)); PORT_Memset(&cryptoMech, 0, sizeof(CK_MECHANISM)); - /* HACK ALERT! - * in this case, key is not actually a PK11SymKey *, but a SEC_PKCS5KeyAndPassword * - */ - keyPwd = (SEC_PKCS5KeyAndPassword *)key; - key = keyPwd->key; + pwitem = PK11_GetSymKeyUserData(key); + if (!pwitem) + return NULL; /* find correct PK11 mechanism and parameters to initialize pbeMech */ pbeMech.mechanism = PK11_AlgtagToMechanism(algtag); @@ -114,7 +111,7 @@ NSS_CMSCipherContext_StartDecrypt(PK11SymKey *key, SECAlgorithmID *algid) pbeMech.ulParameterLen = pbeParams->len; /* now map pbeMech to cryptoMech */ - if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, keyPwd->pwitem, + if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, pwitem, PR_FALSE) != CKR_OK) { SECITEM_ZfreeItem(pbeParams, PR_TRUE); return NULL; @@ -187,17 +184,14 @@ NSS_CMSCipherContext_StartEncrypt(PRArenaPool *poolp, PK11SymKey *key, SECAlgori /* set param and mechanism */ if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { CK_MECHANISM pbeMech, cryptoMech; - SECItem *pbeParams; - SEC_PKCS5KeyAndPassword *keyPwd; + SECItem *pbeParams, *pwitem; PORT_Memset(&pbeMech, 0, sizeof(CK_MECHANISM)); PORT_Memset(&cryptoMech, 0, sizeof(CK_MECHANISM)); - /* HACK ALERT! - * in this case, key is not actually a PK11SymKey *, but a SEC_PKCS5KeyAndPassword * - */ - keyPwd = (SEC_PKCS5KeyAndPassword *)key; - key = keyPwd->key; + pwitem = PK11_GetSymKeyUserData(key); + if (!pwitem) + return NULL; /* find correct PK11 mechanism and parameters to initialize pbeMech */ pbeMech.mechanism = PK11_AlgtagToMechanism(algtag); @@ -208,7 +202,7 @@ NSS_CMSCipherContext_StartEncrypt(PRArenaPool *poolp, PK11SymKey *key, SECAlgori pbeMech.ulParameterLen = pbeParams->len; /* now map pbeMech to cryptoMech */ - if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, keyPwd->pwitem, + if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, pwitem, PR_FALSE) != CKR_OK) { SECITEM_ZfreeItem(pbeParams, PR_TRUE); return NULL; diff --git a/security/nss/lib/smime/cmsencdata.c b/security/nss/lib/smime/cmsencdata.c index fdf10c02b..0bcbb680a 100644 --- a/security/nss/lib/smime/cmsencdata.c +++ b/security/nss/lib/smime/cmsencdata.c @@ -245,16 +245,6 @@ NSS_CMSEncryptedData_Decode_BeforeData(NSSCMSEncryptedData *encd) if (cinfo->ciphcx == NULL) goto loser; /* error has been set by NSS_CMSCipherContext_StartDecrypt */ - /* - * HACK ALERT!! - * For PKCS5 Encryption Algorithms, the bulkkey is actually a different - * structure. Therefore, we need to set the bulkkey to the actual key - * prior to freeing it. - */ - if (SEC_PKCS5IsAlgorithmPBEAlg(bulkalg)) { - SEC_PKCS5KeyAndPassword *keyPwd = (SEC_PKCS5KeyAndPassword *)bulkkey; - bulkkey = keyPwd->key; - } /* we are done with (this) bulkkey now. */ PK11_FreeSymKey(bulkkey); diff --git a/security/nss/lib/smime/cmsenvdata.c b/security/nss/lib/smime/cmsenvdata.c index 7b5aaf9c2..c575a995e 100644 --- a/security/nss/lib/smime/cmsenvdata.c +++ b/security/nss/lib/smime/cmsenvdata.c @@ -384,16 +384,6 @@ NSS_CMSEnvelopedData_Decode_BeforeData(NSSCMSEnvelopedData *envd) if (cinfo->ciphcx == NULL) goto loser; /* error has been set by NSS_CMSCipherContext_StartDecrypt */ - /* - * HACK ALERT!! - * For PKCS5 Encryption Algorithms, the bulkkey is actually a different - * structure. Therefore, we need to set the bulkkey to the actual key - * prior to freeing it. - */ - if (SEC_PKCS5IsAlgorithmPBEAlg(bulkalg)) { - SEC_PKCS5KeyAndPassword *keyPwd = (SEC_PKCS5KeyAndPassword *)bulkkey; - bulkkey = keyPwd->key; - } rv = SECSuccess; diff --git a/security/nss/lib/smime/cmsrecinfo.c b/security/nss/lib/smime/cmsrecinfo.c index 6f0ed119d..07236adc1 100644 --- a/security/nss/lib/smime/cmsrecinfo.c +++ b/security/nss/lib/smime/cmsrecinfo.c @@ -63,8 +63,15 @@ nss_cmsrecipientinfo_usessubjectkeyid(NSSCMSRecipientInfo *ri) return PR_FALSE; } - -static SECOidData fakeContent = { 0 }; +/* + * NOTE: fakeContent marks CMSMessage structure which is only used as a carrier + * of pwfn_arg and arena pools. In an ideal world, NSSCMSMessage would not have + * been exported, and we would have added an ordinary enum to handle this + * check. Unfortunatly wo don't have that luxury so we are overloading the + * contentTypeTag field. NO code should every try to interpret this content tag + * as a real OID tag, or use any fields other than pwfn_arg or poolp of this + * CMSMessage for that matter */ +static const SECOidData fakeContent; NSSCMSRecipientInfo * nss_cmsrecipientinfo_create(NSSCMSMessage *cmsg, NSSCMSRecipientIDSelector type, CERTCertificate *cert, SECKEYPublicKey *pubKey, @@ -183,8 +190,8 @@ nss_cmsrecipientinfo_create(NSSCMSMessage *cmsg, NSSCMSRecipientIDSelector type, case SEC_OID_MISSI_KEA_DSS_OLD: case SEC_OID_MISSI_KEA_DSS: case SEC_OID_MISSI_KEA: - PORT_Assert(type != NSSCMSRecipientID_SubjectKeyID); - if (type == NSSCMSRecipientID_SubjectKeyID) { + PORT_Assert(type == NSSCMSRecipientID_IssuerSN); + if (type != NSSCMSRecipientID_IssuerSN) { rv = SECFailure; break; } @@ -199,8 +206,8 @@ nss_cmsrecipientinfo_create(NSSCMSMessage *cmsg, NSSCMSRecipientIDSelector type, } break; case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* dh-public-number */ - PORT_Assert(type != NSSCMSRecipientID_SubjectKeyID); - if (type == NSSCMSRecipientID_SubjectKeyID) { + PORT_Assert(type == NSSCMSRecipientID_IssuerSN); + if (type != NSSCMSRecipientID_IssuerSN) { rv = SECFailure; break; } diff --git a/security/nss/lib/smime/cmsreclist.c b/security/nss/lib/smime/cmsreclist.c index 2402c3979..34e31d582 100644 --- a/security/nss/lib/smime/cmsreclist.c +++ b/security/nss/lib/smime/cmsreclist.c @@ -82,6 +82,9 @@ nss_cms_recipients_traverse(NSSCMSRecipientInfo **recipientinfos, NSSCMSRecipien rle->kind = RLSubjKeyID; rle->id.subjectKeyID = ri->ri.keyTransRecipientInfo.recipientIdentifier.id.subjectKeyID; break; + default: + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return -1; } recipient_list[rlindex++] = rle; } else { diff --git a/security/nss/lib/smime/cmssiginfo.c b/security/nss/lib/smime/cmssiginfo.c index a8549128c..675040b66 100644 --- a/security/nss/lib/smime/cmssiginfo.c +++ b/security/nss/lib/smime/cmssiginfo.c @@ -19,6 +19,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -347,7 +348,9 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo, CERTCertificate *cert; NSSCMSVerificationStatus vs = NSSCMSVS_Unverified; PLArenaPool *poolp; - SECOidTag tag; + SECOidTag digestalgtag; + SECOidTag pubkAlgTag; + SECOidTag signAlgTag; if (signerinfo == NULL) return SECFailure; @@ -366,6 +369,8 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo, goto loser; } + digestalgtag = NSS_CMSSignerInfo_GetDigestAlgTag(signerinfo); + /* * XXX This may not be the right set of algorithms to check. * I'd prefer to trust that just calling VFY_Verify{Data,Digest} @@ -374,13 +379,14 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo, * and we would Just Work. So this check should just be removed, * but not until the VFY code is better at setting errors. */ - tag = SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg)); - switch (tag) { + pubkAlgTag = SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg)); + switch (pubkAlgTag) { case SEC_OID_PKCS1_RSA_ENCRYPTION: case SEC_OID_ANSIX9_DSA_SIGNATURE: case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST: case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: + case SEC_OID_ANSIX962_EC_PUBLIC_KEY: /* ok */ break; case SEC_OID_UNKNOWN: @@ -391,6 +397,8 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo, goto loser; } + signAlgTag = NSS_CMSUtil_MakeSignatureAlgorithm(digestalgtag, pubkAlgTag); + if (!NSS_CMSArray_IsEmpty((void **)signerinfo->authAttr)) { if (contentType) { /* @@ -454,8 +462,7 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo, } vs = (VFY_VerifyData (encoded_attrs.data, encoded_attrs.len, - publickey, &(signerinfo->encDigest), - SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg)), + publickey, &(signerinfo->encDigest), signAlgTag, signerinfo->cmsg->pwfn_arg) != SECSuccess) ? NSSCMSVS_BadSignature : NSSCMSVS_GoodSignature; @@ -472,8 +479,7 @@ NSS_CMSSignerInfo_Verify(NSSCMSSignerInfo *signerinfo, goto loser; vs = (!digest || - VFY_VerifyDigest(digest, publickey, sig, - SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg)), + VFY_VerifyDigest(digest, publickey, sig, signAlgTag, signerinfo->cmsg->pwfn_arg) != SECSuccess) ? NSSCMSVS_BadSignature : NSSCMSVS_GoodSignature; } diff --git a/security/nss/lib/smime/cmsutil.c b/security/nss/lib/smime/cmsutil.c index fdb88f639..1765655bb 100644 --- a/security/nss/lib/smime/cmsutil.c +++ b/security/nss/lib/smime/cmsutil.c @@ -19,6 +19,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -115,7 +116,7 @@ NSS_CMSUtil_DERCompare(void *a, void *b) { SECItem *der1 = (SECItem *)a; SECItem *der2 = (SECItem *)b; - int j; + unsigned int j; /* * Find the lowest (lexigraphically) encoding. One that is @@ -255,6 +256,13 @@ NSS_CMSUtil_MakeSignatureAlgorithm(SECOidTag hashalg, SECOidTag encalg) default: return SEC_OID_UNKNOWN; } + case SEC_OID_ANSIX962_EC_PUBLIC_KEY: + switch (hashalg) { + case SEC_OID_SHA1: + return SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST; + default: + return SEC_OID_UNKNOWN; + } default: break; } diff --git a/security/nss/lib/smime/config.mk b/security/nss/lib/smime/config.mk index d7f5c4519..236dd375b 100644 --- a/security/nss/lib/smime/config.mk +++ b/security/nss/lib/smime/config.mk @@ -50,6 +50,7 @@ ifdef NS_USE_GCC EXTRA_SHARED_LIBS += \ -L$(DIST)/lib \ -lnss3 \ + -L$(NSPR_LIB_DIR) \ -lplc4 \ -lplds4 \ -lnspr4 \ @@ -57,17 +58,18 @@ EXTRA_SHARED_LIBS += \ else # ! NS_USE_GCC EXTRA_SHARED_LIBS += \ $(DIST)/lib/nss3.lib \ - $(DIST)/lib/$(NSPR31_LIB_PREFIX)plc4.lib \ - $(DIST)/lib/$(NSPR31_LIB_PREFIX)plds4.lib \ - $(DIST)/lib/$(NSPR31_LIB_PREFIX)nspr4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \ $(NULL) endif # NS_USE_GCC else EXTRA_SHARED_LIBS += \ - -L$(DIST)/lib/ \ + -L$(DIST)/lib \ -lnss3 \ + -L$(NSPR_LIB_DIR) \ -lplc4 \ -lplds4 \ -lnspr4 \ @@ -95,4 +97,3 @@ ifeq ($(OS_TARGET),SunOS) # dependencies in the same directory where it resides. MKSHLIB += -R '$$ORIGIN' endif - diff --git a/security/nss/lib/softoken/cdbhdl.h b/security/nss/lib/softoken/cdbhdl.h index a53aacea3..238a48669 100644 --- a/security/nss/lib/softoken/cdbhdl.h +++ b/security/nss/lib/softoken/cdbhdl.h @@ -45,6 +45,7 @@ #include "nspr.h" #include "mcom_db.h" #include "pcertt.h" +#include "prtypes.h" /* * Handle structure for open certificate databases @@ -53,8 +54,11 @@ struct NSSLOWCERTCertDBHandleStr { DB *permCertDB; PZMonitor *dbMon; PRBool dbVerify; + PRInt32 ref; /* reference count */ }; +#define nsslowcert_reference(x) (PR_AtomicIncrement(&(x)->ref) , (x)) + #ifdef DBM_USING_NSPR #define NO_RDONLY PR_RDONLY #define NO_RDWR PR_RDWR diff --git a/security/nss/lib/softoken/config.mk b/security/nss/lib/softoken/config.mk index eabf275dd..2e097c8a5 100644 --- a/security/nss/lib/softoken/config.mk +++ b/security/nss/lib/softoken/config.mk @@ -61,7 +61,7 @@ RESNAME = $(LIBRARY_NAME).rc ifdef NS_USE_GCC EXTRA_SHARED_LIBS += \ - -L$(DIST)/lib \ + -L$(NSPR_LIB_DIR) \ -lplc4 \ -lplds4 \ -lnspr4 \ @@ -69,9 +69,9 @@ EXTRA_SHARED_LIBS += \ else # ! NS_USE_GCC EXTRA_SHARED_LIBS += \ - $(DIST)/lib/$(NSPR31_LIB_PREFIX)plc4.lib \ - $(DIST)/lib/$(NSPR31_LIB_PREFIX)plds4.lib \ - $(DIST)/lib/$(NSPR31_LIB_PREFIX)nspr4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \ $(NULL) endif # NS_USE_GCC @@ -80,7 +80,7 @@ else # $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS) # $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX. EXTRA_SHARED_LIBS += \ - -L$(DIST)/lib/ \ + -L$(NSPR_LIB_DIR) \ -lplc4 \ -lplds4 \ -lnspr4 \ @@ -96,3 +96,6 @@ endif ifeq ($(OS_TARGET),WINCE) DEFINES += -DDBM_USING_NSPR endif + +# indicates dependency on freebl static lib +$(SHARED_LIBRARY): $(CRYPTOLIB) diff --git a/security/nss/lib/softoken/dbinit.c b/security/nss/lib/softoken/dbinit.c index 110419dac..2b7f81a73 100644 --- a/security/nss/lib/softoken/dbinit.c +++ b/security/nss/lib/softoken/dbinit.c @@ -43,10 +43,12 @@ #include "prinit.h" #include "prprf.h" #include "prmem.h" +#include "pratom.h" #include "pcertt.h" #include "lowkeyi.h" #include "pcert.h" #include "cdbhdl.h" +#include "keydbi.h" #include "pkcs11i.h" static char * @@ -164,6 +166,7 @@ sftk_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly, if (certdb == NULL) goto loser; + certdb->ref = 1; /* fix when we get the DB in */ rv = nsslowcert_OpenCertDB(certdb, readOnly, appName, prefix, sftk_certdb_name_cb, (void *)name, PR_FALSE); @@ -254,20 +257,52 @@ loser: return crv; } - -void -sftk_DBShutdown(NSSLOWCERTCertDBHandle *certHandle, - NSSLOWKEYDBHandle *keyHandle) +NSSLOWCERTCertDBHandle * +sftk_getCertDB(SFTKSlot *slot) { + NSSLOWCERTCertDBHandle *certHandle; + + PZ_Lock(slot->slotLock); + certHandle = slot->certDB; if (certHandle) { - nsslowcert_ClosePermCertDB(certHandle); - PORT_Free(certHandle); + PR_AtomicIncrement(&certHandle->ref); } + PZ_Unlock(slot->slotLock); + return certHandle; +} +NSSLOWKEYDBHandle * +sftk_getKeyDB(SFTKSlot *slot) +{ + NSSLOWKEYDBHandle *keyHandle; + + PZ_Lock(slot->slotLock); + keyHandle = slot->keyDB; if (keyHandle) { - nsslowkey_CloseKeyDB(keyHandle); + PR_AtomicIncrement(&keyHandle->ref); } + PZ_Unlock(slot->slotLock); + return keyHandle; +} + +void +sftk_freeCertDB(NSSLOWCERTCertDBHandle *certHandle) +{ + PRInt32 ref = PR_AtomicDecrement(&certHandle->ref); + if (ref == 0) { + nsslowcert_ClosePermCertDB(certHandle); + } +} + +void +sftk_freeKeyDB(NSSLOWKEYDBHandle *keyHandle) +{ + PRInt32 ref = PR_AtomicDecrement(&keyHandle->ref); + if (ref == 0) { + nsslowkey_CloseKeyDB(keyHandle); + } } + static int rdbmapflags(int flags); static rdbfunc sftk_rdbfunc = NULL; diff --git a/security/nss/lib/softoken/fipstest.c b/security/nss/lib/softoken/fipstest.c index 36e8f62d4..acee77676 100644 --- a/security/nss/lib/softoken/fipstest.c +++ b/security/nss/lib/softoken/fipstest.c @@ -68,16 +68,17 @@ #define FIPS_DES3_DECRYPT_LENGTH 8 /* 64-bits */ -/* FIPS preprocessor directives for MD2. */ -#define FIPS_MD2_HASH_MESSAGE_LENGTH 64 /* 512-bits */ +/* FIPS preprocessor directives for AES-ECB and AES-CBC. */ +#define FIPS_AES_BLOCK_SIZE 16 /* 128-bits */ +#define FIPS_AES_ENCRYPT_LENGTH 16 /* 128-bits */ +#define FIPS_AES_DECRYPT_LENGTH 16 /* 128-bits */ +#define FIPS_AES_128_KEY_SIZE 16 /* 128-bits */ +#define FIPS_AES_192_KEY_SIZE 24 /* 192-bits */ +#define FIPS_AES_256_KEY_SIZE 32 /* 256-bits */ -/* FIPS preprocessor directives for MD5. */ -#define FIPS_MD5_HASH_MESSAGE_LENGTH 64 /* 512-bits */ - - -/* FIPS preprocessor directives for SHA-1. */ -#define FIPS_SHA1_HASH_MESSAGE_LENGTH 64 /* 512-bits */ +/* FIPS preprocessor directives for message digests */ +#define FIPS_KNOWN_HASH_MESSAGE_LENGTH 64 /* 512-bits */ /* FIPS preprocessor directives for RSA. */ @@ -562,17 +563,186 @@ sftk_fips_DES3_PowerUpSelfTest( void ) } +/* AES self-test for 128-bit, 192-bit, or 256-bit key sizes*/ static CK_RV -sftk_fips_MD2_PowerUpSelfTest( void ) +sftk_fips_AES_PowerUpSelfTest( int aes_key_size ) { - /* MD2 Known Hash Message (512-bits). */ - static const PRUint8 md2_known_hash_message[] = { - "The test message for the MD2, MD5, and SHA-1 hashing algorithms." }; + /* AES Known Key (up to 256-bits). */ + static const PRUint8 aes_known_key[] = + { "AES-128 RIJNDAELLEADNJIR 821-SEA" }; + + /* AES-CBC Known Initialization Vector (128-bits). */ + static const PRUint8 aes_cbc_known_initialization_vector[] = + { "SecurityytiruceS" }; + + /* AES Known Plaintext (128-bits). (blocksize is 128-bits) */ + static const PRUint8 aes_known_plaintext[] = { "NetscapeepacsteN" }; + + /* AES Known Ciphertext (128-bit key). */ + static const PRUint8 aes_ecb128_known_ciphertext[] = { + 0x3c,0xa5,0x96,0xf3,0x34,0x6a,0x96,0xc1, + 0x03,0x88,0x16,0x7b,0x20,0xbf,0x35,0x47 }; + + static const PRUint8 aes_cbc128_known_ciphertext[] = { + 0xcf,0x15,0x1d,0x4f,0x96,0xe4,0x4f,0x63, + 0x15,0x54,0x14,0x1d,0x4e,0xd8,0xd5,0xea }; + + /* AES Known Ciphertext (192-bit key). */ + static const PRUint8 aes_ecb192_known_ciphertext[] = { + 0xa0,0x18,0x62,0xed,0x88,0x19,0xcb,0x62, + 0x88,0x1d,0x4d,0xfe,0x84,0x02,0x89,0x0e }; + + static const PRUint8 aes_cbc192_known_ciphertext[] = { + 0x83,0xf7,0xa4,0x76,0xd1,0x6f,0x07,0xbe, + 0x07,0xbc,0x43,0x2f,0x6d,0xad,0x29,0xe1 }; + + /* AES Known Ciphertext (256-bit key). */ + static const PRUint8 aes_ecb256_known_ciphertext[] = { + 0xdb,0xa6,0x52,0x01,0x8a,0x70,0xae,0x66, + 0x3a,0x99,0xd8,0x95,0x7f,0xfb,0x01,0x67 }; + + static const PRUint8 aes_cbc256_known_ciphertext[] = { + 0x37,0xea,0x07,0x06,0x31,0x1c,0x59,0x27, + 0xc5,0xc5,0x68,0x71,0x6e,0x34,0x40,0x16 }; + + const PRUint8 *aes_ecb_known_ciphertext = + ( aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_ecb128_known_ciphertext : + ( aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_ecb192_known_ciphertext : + aes_ecb256_known_ciphertext; + + const PRUint8 *aes_cbc_known_ciphertext = + ( aes_key_size == FIPS_AES_128_KEY_SIZE) ? aes_cbc128_known_ciphertext : + ( aes_key_size == FIPS_AES_192_KEY_SIZE) ? aes_cbc192_known_ciphertext : + aes_cbc256_known_ciphertext; + + /* AES variables. */ + PRUint8 aes_computed_ciphertext[FIPS_AES_ENCRYPT_LENGTH]; + PRUint8 aes_computed_plaintext[FIPS_AES_DECRYPT_LENGTH]; + AESContext * aes_context; + unsigned int aes_bytes_encrypted; + unsigned int aes_bytes_decrypted; + SECStatus aes_status; + + /*check if aes_key_size is 128, 192, or 256 bits */ + if ((aes_key_size != FIPS_AES_128_KEY_SIZE) && + (aes_key_size != FIPS_AES_192_KEY_SIZE) && + (aes_key_size != FIPS_AES_256_KEY_SIZE)) + return( CKR_DEVICE_ERROR ); + + /******************************************************/ + /* AES-ECB Single-Round Known Answer Encryption Test: */ + /******************************************************/ + + aes_context = AES_CreateContext( aes_known_key, NULL, NSS_AES, PR_TRUE, + aes_key_size, FIPS_AES_BLOCK_SIZE ); + + if( aes_context == NULL ) + return( CKR_HOST_MEMORY ); + + aes_status = AES_Encrypt( aes_context, aes_computed_ciphertext, + &aes_bytes_encrypted, FIPS_AES_ENCRYPT_LENGTH, + aes_known_plaintext, + FIPS_AES_DECRYPT_LENGTH ); + + AES_DestroyContext( aes_context, PR_TRUE ); + + if( ( aes_status != SECSuccess ) || + ( aes_bytes_encrypted != FIPS_AES_ENCRYPT_LENGTH ) || + ( PORT_Memcmp( aes_computed_ciphertext, aes_ecb_known_ciphertext, + FIPS_AES_ENCRYPT_LENGTH ) != 0 ) ) + return( CKR_DEVICE_ERROR ); + + + /******************************************************/ + /* AES-ECB Single-Round Known Answer Decryption Test: */ + /******************************************************/ + + aes_context = AES_CreateContext( aes_known_key, NULL, NSS_AES, PR_FALSE, + aes_key_size, FIPS_AES_BLOCK_SIZE ); + + if( aes_context == NULL ) + return( CKR_HOST_MEMORY ); + + aes_status = AES_Decrypt( aes_context, aes_computed_plaintext, + &aes_bytes_decrypted, FIPS_AES_DECRYPT_LENGTH, + aes_ecb_known_ciphertext, + FIPS_AES_ENCRYPT_LENGTH ); + + AES_DestroyContext( aes_context, PR_TRUE ); + + if( ( aes_status != SECSuccess ) || + ( aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH ) || + ( PORT_Memcmp( aes_computed_plaintext, aes_known_plaintext, + FIPS_AES_DECRYPT_LENGTH ) != 0 ) ) + return( CKR_DEVICE_ERROR ); + + /******************************************************/ + /* AES-CBC Single-Round Known Answer Encryption Test. */ + /******************************************************/ + + aes_context = AES_CreateContext( aes_known_key, + aes_cbc_known_initialization_vector, + NSS_AES_CBC, PR_TRUE, aes_key_size, + FIPS_AES_BLOCK_SIZE ); + + if( aes_context == NULL ) + return( CKR_HOST_MEMORY ); + + aes_status = AES_Encrypt( aes_context, aes_computed_ciphertext, + &aes_bytes_encrypted, FIPS_AES_ENCRYPT_LENGTH, + aes_known_plaintext, + FIPS_AES_DECRYPT_LENGTH ); + + AES_DestroyContext( aes_context, PR_TRUE ); + + if( ( aes_status != SECSuccess ) || + ( aes_bytes_encrypted != FIPS_AES_ENCRYPT_LENGTH ) || + ( PORT_Memcmp( aes_computed_ciphertext, aes_cbc_known_ciphertext, + FIPS_AES_ENCRYPT_LENGTH ) != 0 ) ) + return( CKR_DEVICE_ERROR ); + + + /******************************************************/ + /* AES-CBC Single-Round Known Answer Decryption Test. */ + /******************************************************/ + + aes_context = AES_CreateContext( aes_known_key, + aes_cbc_known_initialization_vector, + NSS_AES_CBC, PR_FALSE, aes_key_size, + FIPS_AES_BLOCK_SIZE ); + + if( aes_context == NULL ) + return( CKR_HOST_MEMORY ); + + aes_status = AES_Decrypt( aes_context, aes_computed_plaintext, + &aes_bytes_decrypted, FIPS_AES_DECRYPT_LENGTH, + aes_cbc_known_ciphertext, + FIPS_AES_ENCRYPT_LENGTH ); + + AES_DestroyContext( aes_context, PR_TRUE ); + + if( ( aes_status != SECSuccess ) || + ( aes_bytes_decrypted != FIPS_AES_DECRYPT_LENGTH ) || + ( PORT_Memcmp( aes_computed_plaintext, aes_known_plaintext, + FIPS_AES_DECRYPT_LENGTH ) != 0 ) ) + return( CKR_DEVICE_ERROR ); + + return( CKR_OK ); +} + +/* Known Hash Message (512-bits). Used for all hashes (incl. SHA-N [N>1]). */ +static const PRUint8 known_hash_message[] = { + "The test message for the MD2, MD5, and SHA-1 hashing algorithms." }; + + +static CK_RV +sftk_fips_MD2_PowerUpSelfTest( void ) +{ /* MD2 Known Digest Message (128-bits). */ static const PRUint8 md2_known_digest[] = { - 0x41,0x5a,0x12,0xb2,0x3f,0x28,0x97,0x17, - 0x0c,0x71,0x4e,0xcc,0x40,0xc8,0x1d,0x1b}; + 0x41,0x5a,0x12,0xb2,0x3f,0x28,0x97,0x17, + 0x0c,0x71,0x4e,0xcc,0x40,0xc8,0x1d,0x1b}; /* MD2 variables. */ MD2Context * md2_context; @@ -591,13 +761,13 @@ sftk_fips_MD2_PowerUpSelfTest( void ) MD2_Begin( md2_context ); - MD2_Update( md2_context, md2_known_hash_message, - FIPS_MD2_HASH_MESSAGE_LENGTH ); + MD2_Update( md2_context, known_hash_message, + FIPS_KNOWN_HASH_MESSAGE_LENGTH ); MD2_End( md2_context, md2_computed_digest, &md2_bytes_hashed, MD2_LENGTH ); MD2_DestroyContext( md2_context , PR_TRUE ); - + if( ( md2_bytes_hashed != MD2_LENGTH ) || ( PORT_Memcmp( md2_computed_digest, md2_known_digest, MD2_LENGTH ) != 0 ) ) @@ -610,10 +780,6 @@ sftk_fips_MD2_PowerUpSelfTest( void ) static CK_RV sftk_fips_MD5_PowerUpSelfTest( void ) { - /* MD5 Known Hash Message (512-bits). */ - static const PRUint8 md5_known_hash_message[] = { - "The test message for the MD2, MD5, and SHA-1 hashing algorithms." }; - /* MD5 Known Digest Message (128-bits). */ static const PRUint8 md5_known_digest[] = { 0x25,0xc8,0xc0,0x10,0xc5,0x6e,0x68,0x28, @@ -628,8 +794,8 @@ sftk_fips_MD5_PowerUpSelfTest( void ) /* MD5 Single-Round Known Answer Hashing Test. */ /***********************************************/ - md5_status = MD5_HashBuf( md5_computed_digest, md5_known_hash_message, - FIPS_MD5_HASH_MESSAGE_LENGTH ); + md5_status = MD5_HashBuf( md5_computed_digest, known_hash_message, + FIPS_KNOWN_HASH_MESSAGE_LENGTH ); if( ( md5_status != SECSuccess ) || ( PORT_Memcmp( md5_computed_digest, md5_known_digest, @@ -639,37 +805,244 @@ sftk_fips_MD5_PowerUpSelfTest( void ) return( CKR_OK ); } +/****************************************************/ +/* Single Round HMAC SHA-X test */ +/****************************************************/ +static SECStatus +sftk_fips_HMAC(unsigned char *hmac_computed, + const PRUint8 *secret_key, + unsigned int secret_key_length, + const PRUint8 *message, + unsigned int message_length, + HASH_HashType hashAlg ) +{ + SECStatus hmac_status = SECFailure; + HMACContext *cx = NULL; + SECHashObject *hashObj = NULL; + unsigned int bytes_hashed = 0; + + hashObj = (SECHashObject *) HASH_GetRawHashObject(hashAlg); + + if (!hashObj) + return( SECFailure ); + + cx = HMAC_Create(hashObj, secret_key, + secret_key_length, + PR_TRUE); /* PR_TRUE for in FIPS mode */ + + if (cx == NULL) + return( SECFailure ); + + HMAC_Begin(cx); + HMAC_Update(cx, message, message_length); + hmac_status = HMAC_Finish(cx, hmac_computed, &bytes_hashed, + hashObj->length); + + HMAC_Destroy(cx, PR_TRUE); + + return( hmac_status ); +} static CK_RV -sftk_fips_SHA1_PowerUpSelfTest( void ) +sftk_fips_HMAC_PowerUpSelfTest( void ) { - /* SHA-1 Known Hash Message (512-bits). */ - static const PRUint8 sha1_known_hash_message[] = { - "The test message for the MD2, MD5, and SHA-1 hashing algorithms." }; + static const PRUint8 HMAC_known_secret_key[] = { + "Firefox and ThunderBird are awesome!"}; + + static const PRUint8 HMAC_known_secret_key_length + = sizeof HMAC_known_secret_key; + + /* known SHA1 hmac (20 bytes) */ + static const PRUint8 known_SHA1_hmac[] = { + 0xd5, 0x85, 0xf6, 0x5b, 0x39, 0xfa, 0xb9, 0x05, + 0x3b, 0x57, 0x1d, 0x61, 0xe7, 0xb8, 0x84, 0x1e, + 0x5d, 0x0e, 0x1e, 0x11}; + + /* known SHA256 hmac (32 bytes) */ + static const PRUint8 known_SHA256_hmac[] = { + 0x05, 0x75, 0x9a, 0x9e, 0x70, 0x5e, 0xe7, 0x44, + 0xe2, 0x46, 0x4b, 0x92, 0x22, 0x14, 0x22, 0xe0, + 0x1b, 0x92, 0x8a, 0x0c, 0xfe, 0xf5, 0x49, 0xe9, + 0xa7, 0x1b, 0x56, 0x7d, 0x1d, 0x29, 0x40, 0x48}; + + /* known SHA384 hmac (48 bytes) */ + static const PRUint8 known_SHA384_hmac[] = { + 0xcd, 0x56, 0x14, 0xec, 0x05, 0x53, 0x06, 0x2b, + 0x7e, 0x9c, 0x8a, 0x18, 0x5e, 0xea, 0xf3, 0x91, + 0x33, 0xfb, 0x64, 0xf6, 0xe3, 0x9f, 0x89, 0x0b, + 0xaf, 0xbe, 0x83, 0x4d, 0x3f, 0x3c, 0x43, 0x4d, + 0x4a, 0x0c, 0x56, 0x98, 0xf8, 0xca, 0xb4, 0xaa, + 0x9a, 0xf4, 0x0a, 0xaf, 0x4f, 0x69, 0xca, 0x87}; + + /* known SHA512 hmac (64 bytes) */ + static const PRUint8 known_SHA512_hmac[] = { + 0xf6, 0x0e, 0x97, 0x12, 0x00, 0x67, 0x6e, 0xb9, + 0x0c, 0xb2, 0x63, 0xf0, 0x60, 0xac, 0x75, 0x62, + 0x70, 0x95, 0x2a, 0x52, 0x22, 0xee, 0xdd, 0xd2, + 0x71, 0xb1, 0xe8, 0x26, 0x33, 0xd3, 0x13, 0x27, + 0xcb, 0xff, 0x44, 0xef, 0x87, 0x97, 0x16, 0xfb, + 0xd3, 0x0b, 0x48, 0xbe, 0x12, 0x4e, 0xda, 0xb1, + 0x89, 0x90, 0xfb, 0x06, 0x0c, 0xbe, 0xe5, 0xc4, + 0xff, 0x24, 0x37, 0x3d, 0xc7, 0xe4, 0xe4, 0x37}; + + SECStatus hmac_status; + PRUint8 hmac_computed[HASH_LENGTH_MAX]; + + /***************************************************/ + /* HMAC SHA-1 Single-Round Known Answer HMAC Test. */ + /***************************************************/ + + hmac_status = sftk_fips_HMAC(hmac_computed, + HMAC_known_secret_key, + HMAC_known_secret_key_length, + known_hash_message, + FIPS_KNOWN_HASH_MESSAGE_LENGTH, + HASH_AlgSHA1); + + if( ( hmac_status != SECSuccess ) || + ( PORT_Memcmp( hmac_computed, known_SHA1_hmac, + SHA1_LENGTH ) != 0 ) ) + return( CKR_DEVICE_ERROR ); + + /***************************************************/ + /* HMAC SHA-256 Single-Round Known Answer Test. */ + /***************************************************/ + + hmac_status = sftk_fips_HMAC(hmac_computed, + HMAC_known_secret_key, + HMAC_known_secret_key_length, + known_hash_message, + FIPS_KNOWN_HASH_MESSAGE_LENGTH, + HASH_AlgSHA256); + + if( ( hmac_status != SECSuccess ) || + ( PORT_Memcmp( hmac_computed, known_SHA256_hmac, + SHA256_LENGTH ) != 0 ) ) + return( CKR_DEVICE_ERROR ); + + /***************************************************/ + /* HMAC SHA-384 Single-Round Known Answer Test. */ + /***************************************************/ + hmac_status = sftk_fips_HMAC(hmac_computed, + HMAC_known_secret_key, + HMAC_known_secret_key_length, + known_hash_message, + FIPS_KNOWN_HASH_MESSAGE_LENGTH, + HASH_AlgSHA384); + + if( ( hmac_status != SECSuccess ) || + ( PORT_Memcmp( hmac_computed, known_SHA384_hmac, + SHA384_LENGTH ) != 0 ) ) + return( CKR_DEVICE_ERROR ); + + /***************************************************/ + /* HMAC SHA-512 Single-Round Known Answer Test. */ + /***************************************************/ + + hmac_status = sftk_fips_HMAC(hmac_computed, + HMAC_known_secret_key, + HMAC_known_secret_key_length, + known_hash_message, + FIPS_KNOWN_HASH_MESSAGE_LENGTH, + HASH_AlgSHA512); + + if( ( hmac_status != SECSuccess ) || + ( PORT_Memcmp( hmac_computed, known_SHA512_hmac, + SHA512_LENGTH ) != 0 ) ) + return( CKR_DEVICE_ERROR ); + + return( CKR_OK ); +} + +static CK_RV +sftk_fips_SHA_PowerUpSelfTest( void ) +{ /* SHA-1 Known Digest Message (160-bits). */ static const PRUint8 sha1_known_digest[] = { 0x0a,0x6d,0x07,0xba,0x1e,0xbd,0x8a,0x1b, 0x72,0xf6,0xc7,0x22,0xf1,0x27,0x9f,0xf0, 0xe0,0x68,0x47,0x7a}; - /* SHA-1 variables. */ - PRUint8 sha1_computed_digest[SHA1_LENGTH]; - SECStatus sha1_status; - + /* SHA-256 Known Digest Message (256-bits). */ + static const PRUint8 sha256_known_digest[] = { + 0x38,0xa9,0xc1,0xf0,0x35,0xf6,0x5d,0x61, + 0x11,0xd4,0x0b,0xdc,0xce,0x35,0x14,0x8d, + 0xf2,0xdd,0xaf,0xaf,0xcf,0xb7,0x87,0xe9, + 0x96,0xa5,0xd2,0x83,0x62,0x46,0x56,0x79}; + + /* SHA-384 Known Digest Message (384-bits). */ + static const PRUint8 sha384_known_digest[] = { + 0x11,0xfe,0x1c,0x00,0x89,0x48,0xde,0xb3, + 0x99,0xee,0x1c,0x18,0xb4,0x10,0xfb,0xfe, + 0xe3,0xa8,0x2c,0xf3,0x04,0xb0,0x2f,0xc8, + 0xa3,0xc4,0x5e,0xea,0x7e,0x60,0x48,0x7b, + 0xce,0x2c,0x62,0xf7,0xbc,0xa7,0xe8,0xa3, + 0xcf,0x24,0xce,0x9c,0xe2,0x8b,0x09,0x72}; + + /* SHA-512 Known Digest Message (512-bits). */ + static const PRUint8 sha512_known_digest[] = { + 0xc8,0xb3,0x27,0xf9,0x0b,0x24,0xc8,0xbf, + 0x4c,0xba,0x33,0x54,0xf2,0x31,0xbf,0xdb, + 0xab,0xfd,0xb3,0x15,0xd7,0xfa,0x48,0x99, + 0x07,0x60,0x0f,0x57,0x41,0x1a,0xdd,0x28, + 0x12,0x55,0x25,0xac,0xba,0x3a,0x99,0x12, + 0x2c,0x7a,0x8f,0x75,0x3a,0xe1,0x06,0x6f, + 0x30,0x31,0xc9,0x33,0xc6,0x1b,0x90,0x1a, + 0x6c,0x98,0x9a,0x87,0xd0,0xb2,0xf8,0x07}; + + /* SHA-X variables. */ + PRUint8 sha_computed_digest[HASH_LENGTH_MAX]; + SECStatus sha_status; /*************************************************/ /* SHA-1 Single-Round Known Answer Hashing Test. */ /*************************************************/ - sha1_status = SHA1_HashBuf( sha1_computed_digest, sha1_known_hash_message, - FIPS_SHA1_HASH_MESSAGE_LENGTH ); - - if( ( sha1_status != SECSuccess ) || - ( PORT_Memcmp( sha1_computed_digest, sha1_known_digest, + sha_status = SHA1_HashBuf( sha_computed_digest, known_hash_message, + FIPS_KNOWN_HASH_MESSAGE_LENGTH ); + + if( ( sha_status != SECSuccess ) || + ( PORT_Memcmp( sha_computed_digest, sha1_known_digest, SHA1_LENGTH ) != 0 ) ) return( CKR_DEVICE_ERROR ); + /***************************************************/ + /* SHA-256 Single-Round Known Answer Hashing Test. */ + /***************************************************/ + + sha_status = SHA256_HashBuf( sha_computed_digest, known_hash_message, + FIPS_KNOWN_HASH_MESSAGE_LENGTH ); + + if( ( sha_status != SECSuccess ) || + ( PORT_Memcmp( sha_computed_digest, sha256_known_digest, + SHA256_LENGTH ) != 0 ) ) + return( CKR_DEVICE_ERROR ); + + /***************************************************/ + /* SHA-384 Single-Round Known Answer Hashing Test. */ + /***************************************************/ + + sha_status = SHA384_HashBuf( sha_computed_digest, known_hash_message, + FIPS_KNOWN_HASH_MESSAGE_LENGTH ); + + if( ( sha_status != SECSuccess ) || + ( PORT_Memcmp( sha_computed_digest, sha384_known_digest, + SHA384_LENGTH ) != 0 ) ) + return( CKR_DEVICE_ERROR ); + + /***************************************************/ + /* SHA-512 Single-Round Known Answer Hashing Test. */ + /***************************************************/ + + sha_status = SHA512_HashBuf( sha_computed_digest, known_hash_message, + FIPS_KNOWN_HASH_MESSAGE_LENGTH ); + + if( ( sha_status != SECSuccess ) || + ( PORT_Memcmp( sha_computed_digest, sha512_known_digest, + SHA512_LENGTH ) != 0 ) ) + return( CKR_DEVICE_ERROR ); + return( CKR_OK ); } @@ -872,7 +1245,8 @@ sftk_fips_RSA_PowerUpSelfTest( void ) /* Perform RSA signature with the RSA private key. */ rsa_status = RSA_Sign( rsa_private_key, rsa_computed_signature, &rsa_bytes_signed, - FIPS_RSA_SIGNATURE_LENGTH, (unsigned char *)rsa_known_message, + FIPS_RSA_SIGNATURE_LENGTH, + (unsigned char *)rsa_known_message, FIPS_RSA_MESSAGE_LENGTH ); if( ( rsa_status != SECSuccess ) || @@ -1059,6 +1433,24 @@ sftk_fipsPowerUpSelfTest( void ) if( rv != CKR_OK ) return rv; + + /* AES Power-Up SelfTest(s) for 128-bit key. */ + rv = sftk_fips_AES_PowerUpSelfTest(FIPS_AES_128_KEY_SIZE); + + if( rv != CKR_OK ) + return rv; + + /* AES Power-Up SelfTest(s) for 192-bit key. */ + rv = sftk_fips_AES_PowerUpSelfTest(FIPS_AES_192_KEY_SIZE); + + if( rv != CKR_OK ) + return rv; + + /* AES Power-Up SelfTest(s) for 256-bit key. */ + rv = sftk_fips_AES_PowerUpSelfTest(FIPS_AES_256_KEY_SIZE); + + if( rv != CKR_OK ) + return rv; /* MD2 Power-Up SelfTest(s). */ rv = sftk_fips_MD2_PowerUpSelfTest(); @@ -1072,9 +1464,15 @@ sftk_fipsPowerUpSelfTest( void ) if( rv != CKR_OK ) return rv; - /* SHA-1 Power-Up SelfTest(s). */ - rv = sftk_fips_SHA1_PowerUpSelfTest(); + /* SHA-X Power-Up SelfTest(s). */ + rv = sftk_fips_SHA_PowerUpSelfTest(); + + if( rv != CKR_OK ) + return rv; + /* HMAC SHA-X Power-Up SelfTest(s). */ + rv = sftk_fips_HMAC_PowerUpSelfTest(); + if( rv != CKR_OK ) return rv; diff --git a/security/nss/lib/softoken/fipstokn.c b/security/nss/lib/softoken/fipstokn.c index af0e957be..9ef144cb8 100644 --- a/security/nss/lib/softoken/fipstokn.c +++ b/security/nss/lib/softoken/fipstokn.c @@ -56,6 +56,8 @@ #include "pkcs11.h" #include "pkcs11i.h" +#include <ctype.h> + /* * ******************** Password Utilities ******************************* @@ -63,7 +65,101 @@ static PRBool isLoggedIn = PR_FALSE; static PRBool fatalError = PR_FALSE; -/* Fips required checks before any useful crypto graphic services */ +/* + * This function returns + * - CKR_PIN_INVALID if the password/PIN is not a legal UTF8 string + * - CKR_PIN_LEN_RANGE if the password/PIN is too short or does not + * consist of characters from three or more character classes. + * - CKR_OK otherwise + * + * The minimum password/PIN length is FIPS_MIN_PIN Unicode characters. + * We define five character classes: digits (0-9), ASCII lowercase letters, + * ASCII uppercase letters, ASCII non-alphanumeric characters (such as + * space and punctuation marks), and non-ASCII characters. If an ASCII + * uppercase letter is the first character of the password/PIN, the + * uppercase letter is not counted toward its character class. Similarly, + * if a digit is the last character of the password/PIN, the digit is not + * counted toward its character class. + * + * Although NSC_SetPIN and NSC_InitPIN already do the maximum and minimum + * password/PIN length checks, they check the length in bytes as opposed + * to characters. To meet the minimum password/PIN guessing probability + * requirements in FIPS 140-2, we need to check the length in characters. + */ +static CK_RV sftk_newPinCheck(CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { + unsigned int i; + int nchar = 0; /* number of characters */ + int ntrail = 0; /* number of trailing bytes to follow */ + int ndigit = 0; /* number of decimal digits */ + int nlower = 0; /* number of ASCII lowercase letters */ + int nupper = 0; /* number of ASCII uppercase letters */ + int nnonalnum = 0; /* number of ASCII non-alphanumeric characters */ + int nnonascii = 0; /* number of non-ASCII characters */ + int nclass; /* number of character classes */ + + for (i = 0; i < ulPinLen; i++) { + unsigned int byte = pPin[i]; + + if (ntrail) { + if ((byte & 0xc0) != 0x80) { + /* illegal */ + nchar = -1; + break; + } + if (--ntrail == 0) { + nchar++; + nnonascii++; + } + continue; + } + if ((byte & 0x80) == 0x00) { + /* single-byte (ASCII) character */ + nchar++; + if (isdigit(byte)) { + if (i < ulPinLen - 1) { + ndigit++; + } + } else if (islower(byte)) { + nlower++; + } else if (isupper(byte)) { + if (i > 0) { + nupper++; + } + } else { + nnonalnum++; + } + } else if ((byte & 0xe0) == 0xc0) { + /* leading byte of two-byte character */ + ntrail = 1; + } else if ((byte & 0xf0) == 0xe0) { + /* leading byte of three-byte character */ + ntrail = 2; + } else if ((byte & 0xf8) == 0xf0) { + /* leading byte of four-byte character */ + ntrail = 3; + } else { + /* illegal */ + nchar = -1; + break; + } + } + if (nchar == -1) { + /* illegal UTF8 string */ + return CKR_PIN_INVALID; + } + if (nchar < FIPS_MIN_PIN) { + return CKR_PIN_LEN_RANGE; + } + nclass = (ndigit != 0) + (nlower != 0) + (nupper != 0) + + (nnonalnum != 0) + (nnonascii != 0); + if (nclass < 3) { + return CKR_PIN_LEN_RANGE; + } + return CKR_OK; +} + + +/* FIPS required checks before any useful cryptographic services */ static CK_RV sftk_fipsCheck(void) { if (isLoggedIn != PR_TRUE) return CKR_USER_NOT_LOGGED_IN; @@ -273,13 +369,16 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { /* FC_InitToken initializes a token. */ CK_RV FC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin, CK_ULONG usPinLen,CK_CHAR_PTR pLabel) { - return CKR_HOST_MEMORY; /*is this the right function for not implemented*/ + return NSC_InitToken(slotID,pPin,usPinLen,pLabel); } /* FC_InitPIN initializes the normal user's PIN. */ CK_RV FC_InitPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { + CK_RV rv; + SFTK_FIPSFATALCHECK(); + if ((rv = sftk_newPinCheck(pPin,ulPinLen)) != CKR_OK) return rv; return NSC_InitPIN(hSession,pPin,ulPinLen); } @@ -290,6 +389,7 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_ULONG usOldLen, CK_CHAR_PTR pNewPin, CK_ULONG usNewLen) { CK_RV rv; if ((rv = sftk_fipsCheck()) != CKR_OK) return rv; + if ((rv = sftk_newPinCheck(pNewPin,usNewLen)) != CKR_OK) return rv; return NSC_SetPIN(hSession,pOldPin,usOldLen,pNewPin,usNewLen); } @@ -455,7 +555,7 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV FC_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,CK_ULONG usCount) { /* let publically readable object be found */ - int i; + unsigned int i; CK_RV rv; PRBool needLogin = PR_FALSE; @@ -780,6 +880,7 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_ULONG usPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey) { CK_BBOOL *boolptr; + CK_RV crv; SFTK_FIPSCHECK(); @@ -792,9 +893,14 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { return CKR_ATTRIBUTE_VALUE_INVALID; } } - return NSC_GenerateKeyPair (hSession,pMechanism,pPublicKeyTemplate, + crv = NSC_GenerateKeyPair (hSession,pMechanism,pPublicKeyTemplate, usPublicKeyAttributeCount,pPrivateKeyTemplate, usPrivateKeyAttributeCount,phPublicKey,phPrivateKey); + if (crv == CKR_GENERAL_ERROR) { + /* pairwise consistency check failed. */ + fatalError = PR_TRUE; + } + return crv; } diff --git a/security/nss/lib/softoken/keydb.c b/security/nss/lib/softoken/keydb.c index 8ab56ec5b..2f685a5a6 100644 --- a/security/nss/lib/softoken/keydb.c +++ b/security/nss/lib/softoken/keydb.c @@ -161,20 +161,21 @@ free_dbt(DBT *dbt) return; } -static int keydb_Get(DB *db, DBT *key, DBT *data, unsigned int flags); -static int keydb_Put(DB *db, DBT *key, DBT *data, unsigned int flags); -static int keydb_Sync(DB *db, unsigned int flags); -static int keydb_Del(DB *db, DBT *key, unsigned int flags); -static int keydb_Seq(DB *db, DBT *key, DBT *data, unsigned int flags); -static void keydb_Close(DB *db); - -static PZLock *kdbLock = NULL; +static int keydb_Get(NSSLOWKEYDBHandle *db, DBT *key, DBT *data, + unsigned int flags); +static int keydb_Put(NSSLOWKEYDBHandle *db, DBT *key, DBT *data, + unsigned int flags); +static int keydb_Sync(NSSLOWKEYDBHandle *db, unsigned int flags); +static int keydb_Del(NSSLOWKEYDBHandle *db, DBT *key, unsigned int flags); +static int keydb_Seq(NSSLOWKEYDBHandle *db, DBT *key, DBT *data, + unsigned int flags); +static void keydb_Close(NSSLOWKEYDBHandle *db); static void keydb_InitLocks(NSSLOWKEYDBHandle *handle) { - if (kdbLock == NULL) { - nss_InitLock(&kdbLock, nssILockKeyDB); + if (handle->lock == NULL) { + nss_InitLock(&handle->lock, nssILockKeyDB); } return; @@ -183,9 +184,9 @@ keydb_InitLocks(NSSLOWKEYDBHandle *handle) static void keydb_DestroyLocks(NSSLOWKEYDBHandle *handle) { - if (kdbLock != NULL) { - PZ_DestroyLock(kdbLock); - kdbLock = NULL; + if (handle->lock != NULL) { + PZ_DestroyLock(handle->lock); + handle->lock = NULL; } return; @@ -348,7 +349,7 @@ get_dbkey(NSSLOWKEYDBHandle *handle, DBT *index) int ret; /* get it from the database */ - ret = keydb_Get(handle->db, index, &entry, 0); + ret = keydb_Get(handle, index, &entry, 0); if ( ret ) { PORT_SetError(SEC_ERROR_BAD_DATABASE); return NULL; @@ -374,9 +375,9 @@ put_dbkey(NSSLOWKEYDBHandle *handle, DBT *index, NSSLOWKEYDBKey *dbkey, PRBool u /* put it in the database */ if ( update ) { - status = keydb_Put(handle->db, index, keydata, 0); + status = keydb_Put(handle, index, keydata, 0); } else { - status = keydb_Put(handle->db, index, keydata, R_NOOVERWRITE); + status = keydb_Put(handle, index, keydata, R_NOOVERWRITE); } if ( status ) { @@ -384,7 +385,7 @@ put_dbkey(NSSLOWKEYDBHandle *handle, DBT *index, NSSLOWKEYDBKey *dbkey, PRBool u } /* sync the database */ - status = keydb_Sync(handle->db, 0); + status = keydb_Sync(handle, 0); if ( status ) { goto loser; } @@ -414,7 +415,7 @@ nsslowkey_TraverseKeys(NSSLOWKEYDBHandle *handle, return(SECFailure); } - ret = keydb_Seq(handle->db, &key, &data, R_FIRST); + ret = keydb_Seq(handle, &key, &data, R_FIRST); if ( ret ) { return(SECFailure); } @@ -441,7 +442,7 @@ nsslowkey_TraverseKeys(NSSLOWKEYDBHandle *handle, return(status); } } - } while ( keydb_Seq(handle->db, &key, &data, R_NEXT) == 0 ); + } while ( keydb_Seq(handle, &key, &data, R_NEXT) == 0 ); return(SECSuccess); } @@ -521,7 +522,7 @@ GetKeyDBGlobalSalt(NSSLOWKEYDBHandle *handle) saltKey.data = SALT_STRING; saltKey.size = sizeof(SALT_STRING) - 1; - ret = keydb_Get(handle->db, &saltKey, &saltData, 0); + ret = keydb_Get(handle, &saltKey, &saltData, 0); if ( ret ) { return(NULL); } @@ -543,7 +544,7 @@ StoreKeyDBGlobalSalt(NSSLOWKEYDBHandle *handle) saltData.size = handle->global_salt->len; /* put global salt into the database now */ - status = keydb_Put(handle->db, &saltKey, &saltData, 0); + status = keydb_Put(handle, &saltKey, &saltData, 0); if ( status ) { return(SECFailure); } @@ -566,7 +567,7 @@ makeGlobalVersion(NSSLOWKEYDBHandle *handle) versionKey.size = sizeof(VERSION_STRING)-1; /* put version string into the database now */ - status = keydb_Put(handle->db, &versionKey, &versionData, 0); + status = keydb_Put(handle, &versionKey, &versionData, 0); if ( status ) { return(SECFailure); } @@ -592,7 +593,7 @@ makeGlobalSalt(NSSLOWKEYDBHandle *handle) RNG_GenerateGlobalRandomBytes(saltbuf, sizeof(saltbuf)); /* put global salt into the database now */ - status = keydb_Put(handle->db, &saltKey, &saltData, 0); + status = keydb_Put(handle, &saltKey, &saltData, 0); if ( status ) { return(SECFailure); } @@ -623,7 +624,7 @@ encodePWCheckEntry(PLArenaPool *arena, SECItem *entry, SECOidTag alg, SECItem *encCheck); static unsigned char -nsslowkey_version(DB *db) +nsslowkey_version(NSSLOWKEYDBHandle *handle) { DBT versionKey; DBT versionData; @@ -631,8 +632,12 @@ nsslowkey_version(DB *db) versionKey.data = VERSION_STRING; versionKey.size = sizeof(VERSION_STRING)-1; + if (handle->db == NULL) { + return 255; + } + /* lookup version string in database */ - ret = keydb_Get( db, &versionKey, &versionData, 0 ); + ret = keydb_Get( handle, &versionKey, &versionData, 0 ); /* error accessing the database */ if ( ret < 0 ) { @@ -646,14 +651,14 @@ nsslowkey_version(DB *db) } static PRBool -seckey_HasAServerKey(DB *db) +seckey_HasAServerKey(NSSLOWKEYDBHandle *handle) { DBT key; DBT data; int ret; PRBool found = PR_FALSE; - ret = keydb_Seq(db, &key, &data, R_FIRST); + ret = keydb_Seq(handle, &key, &data, R_FIRST); if ( ret ) { return PR_FALSE; } @@ -690,10 +695,14 @@ seckey_HasAServerKey(DB *db) } } - } while ( keydb_Seq(db, &key, &data, R_NEXT) == 0 ); + } while ( keydb_Seq(handle, &key, &data, R_NEXT) == 0 ); return found; } + +/* forward declare local create function */ +static NSSLOWKEYDBHandle * nsslowkey_NewHandle(DB *dbHandle); + /* * currently updates key database from v2 to v3 */ @@ -710,18 +719,29 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle) unsigned char version; SECItem *rc4key = NULL; NSSLOWKEYDBKey *dbkey = NULL; + NSSLOWKEYDBHandle *update = NULL; SECItem *oldSalt = NULL; int ret; SECItem checkitem; if ( handle->updatedb == NULL ) { - return(SECSuccess); + return SECSuccess; + } + + /* create a full DB Handle for our update so we + * can use the correct locks for the db primatives */ + update = nsslowkey_NewHandle(handle->updatedb); + if ( update == NULL) { + return SECSuccess; } + /* update has now inherited the database handle */ + handle->updatedb = NULL; + /* * check the version record */ - version = nsslowkey_version(handle->updatedb); + version = nsslowkey_version(update); if (version != 2) { goto done; } @@ -729,7 +749,7 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle) saltKey.data = SALT_STRING; saltKey.size = sizeof(SALT_STRING) - 1; - ret = keydb_Get(handle->updatedb, &saltKey, &saltData, 0); + ret = keydb_Get(update, &saltKey, &saltData, 0); if ( ret ) { /* no salt in old db, so it is corrupted */ goto done; @@ -747,8 +767,7 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle) checkKey.data = KEYDB_PW_CHECK_STRING; checkKey.size = KEYDB_PW_CHECK_LEN; - ret = keydb_Get(handle->updatedb, &checkKey, - &checkData, 0 ); + ret = keydb_Get(update, &checkKey, &checkData, 0 ); if (ret) { /* * if we have a key, but no KEYDB_PW_CHECK_STRING, then this must @@ -756,7 +775,7 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle) * with it. Put a fake entry in so we can identify this db when we do * get the password for it. */ - if (seckey_HasAServerKey(handle->updatedb)) { + if (seckey_HasAServerKey(update)) { DBT fcheckKey; DBT fcheckData; @@ -768,11 +787,11 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle) fcheckData.data = "1"; fcheckData.size = 1; /* put global salt into the new database now */ - ret = keydb_Put( handle->db, &saltKey, &saltData, 0); + ret = keydb_Put( handle, &saltKey, &saltData, 0); if ( ret ) { goto done; } - ret = keydb_Put( handle->db, &fcheckKey, &fcheckData, 0); + ret = keydb_Put( handle, &fcheckKey, &fcheckData, 0); if ( ret ) { goto done; } @@ -781,7 +800,7 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle) } } else { /* put global salt into the new database now */ - ret = keydb_Put( handle->db, &saltKey, &saltData, 0); + ret = keydb_Put( handle, &saltKey, &saltData, 0); if ( ret ) { goto done; } @@ -811,7 +830,7 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle) /* now traverse the database */ - ret = keydb_Seq(handle->updatedb, &key, &data, R_FIRST); + ret = keydb_Seq(update, &key, &data, R_FIRST); if ( ret ) { goto done; } @@ -857,17 +876,15 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle) sec_destroy_dbkey(dbkey); } - } while ( keydb_Seq(handle->updatedb, &key, &data, - R_NEXT) == 0 ); + } while ( keydb_Seq(update, &key, &data, R_NEXT) == 0 ); dbkey = NULL; done: /* sync the database */ - ret = keydb_Sync(handle->db, 0); + ret = keydb_Sync(handle, 0); - keydb_Close(handle->updatedb); - handle->updatedb = NULL; + nsslowkey_CloseKeyDB(update); if ( rc4key ) { SECITEM_FreeItem(rc4key, PR_TRUE); @@ -913,7 +930,7 @@ openNewDB(const char *appName, const char *prefix, const char *dbname, /* force a transactional read, which will verify that one and only one * process attempts the update. */ - if (nsslowkey_version(handle->db) == NSSLOWKEY_DB_FILE_VERSION) { + if (nsslowkey_version(handle) == NSSLOWKEY_DB_FILE_VERSION) { /* someone else has already updated the database for us */ db_FinishTransaction(handle->db, PR_FALSE); db_InitComplete(handle->db); @@ -925,20 +942,35 @@ openNewDB(const char *appName, const char *prefix, const char *dbname, * local database we can update from. */ if (appName) { + NSSLOWKEYDBHandle *updateHandle = nsslowkey_NewHandle(updatedb); updatedb = dbopen( dbname, NO_RDONLY, 0600, DB_HASH, 0 ); - if (updatedb) { - handle->version = nsslowkey_version(updatedb); - if (handle->version != NSSLOWKEY_DB_FILE_VERSION) { - keydb_Close(updatedb); - } else { - db_Copy(handle->db, updatedb); - keydb_Close(updatedb); - db_FinishTransaction(handle->db,PR_FALSE); - db_InitComplete(handle->db); - return SECSuccess; - } + if (!updatedb) { + goto noupdate; } + + /* nsslowkey_version needs a full handle because it calls + * the kdb_Get() function, which needs to lock. + */ + updateHandle = nsslowkey_NewHandle(updatedb); + if (!updateHandle) { + updatedb->close(updatedb); + goto noupdate; + } + + handle->version = nsslowkey_version(updateHandle); + if (handle->version != NSSLOWKEY_DB_FILE_VERSION) { + nsslowkey_CloseKeyDB(updateHandle); + goto noupdate; + } + + /* copy the new DB from the old one */ + db_Copy(handle->db, updatedb); + nsslowkey_CloseKeyDB(updateHandle); + db_FinishTransaction(handle->db,PR_FALSE); + db_InitComplete(handle->db); + return SECSuccess; } +noupdate: /* update the version number */ rv = makeGlobalVersion(handle); @@ -978,7 +1010,7 @@ openNewDB(const char *appName, const char *prefix, const char *dbname, } /* sync the database */ - ret = keydb_Sync(handle->db, 0); + ret = keydb_Sync(handle, 0); if ( ret ) { rv = SECFailure; goto loser; @@ -994,7 +1026,7 @@ loser: static DB * openOldDB(const char *appName, const char *prefix, const char *dbname, - PRBool openflags, int *version) { + PRBool openflags) { DB *db = NULL; if (appName) { @@ -1003,54 +1035,79 @@ openOldDB(const char *appName, const char *prefix, const char *dbname, db = dbopen( dbname, openflags, 0600, DB_HASH, 0 ); } - /* check for correct version number */ - if (db != NULL) { - *version = nsslowkey_version(db); - if (*version != NSSLOWKEY_DB_FILE_VERSION ) { - /* bogus version number record, reset the database */ - keydb_Close( db ); - db = NULL; + return db; +} + +/* check for correct version number */ +static PRBool +verifyVersion(NSSLOWKEYDBHandle *handle) +{ + int version = nsslowkey_version(handle); + + handle->version = version; + if (version != NSSLOWKEY_DB_FILE_VERSION ) { + if (handle->db) { + keydb_Close(handle); + handle->db = NULL; } } - return db; + return handle->db != NULL; } -NSSLOWKEYDBHandle * -nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix, - NSSLOWKEYDBNameFunc namecb, void *cbarg) +static NSSLOWKEYDBHandle * +nsslowkey_NewHandle(DB *dbHandle) { NSSLOWKEYDBHandle *handle; - SECStatus rv; - int openflags; - char *dbname = NULL; - handle = (NSSLOWKEYDBHandle *)PORT_ZAlloc (sizeof(NSSLOWKEYDBHandle)); if (handle == NULL) { PORT_SetError (SEC_ERROR_NO_MEMORY); return NULL; } + handle->appname = NULL; + handle->dbname = NULL; + handle->global_salt = NULL; + handle->updatedb = NULL; + handle->db = dbHandle; + handle->ref = 1; + + keydb_InitLocks(handle); + return handle; +} + +NSSLOWKEYDBHandle * +nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix, + NSSLOWKEYDBNameFunc namecb, void *cbarg) +{ + NSSLOWKEYDBHandle *handle = NULL; + SECStatus rv; + int openflags; + char *dbname = NULL; + + + handle = nsslowkey_NewHandle(NULL); + openflags = readOnly ? NO_RDONLY : NO_RDWR; + dbname = (*namecb)(cbarg, NSSLOWKEY_DB_FILE_VERSION); if ( dbname == NULL ) { goto loser; } - handle->appname = appName ? PORT_Strdup(appName) : NULL ; handle->dbname = (appName == NULL) ? PORT_Strdup(dbname) : (prefix ? PORT_Strdup(prefix) : NULL); handle->readOnly = readOnly; - keydb_InitLocks(handle); - handle->db = openOldDB(appName, prefix, dbname, openflags, - &handle->version); - if (handle->version == 255) { - goto loser; + handle->db = openOldDB(appName, prefix, dbname, openflags); + if (handle->db) { + verifyVersion(handle); + if (handle->version == 255) { + goto loser; + } } - /* if first open fails, try to create a new DB */ if ( handle->db == NULL ) { @@ -1063,8 +1120,8 @@ nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix, * The multiprocess code blocked the second one, then had it retry to * see if it can just open the database normally */ if (rv == SECWouldBlock) { - handle->db = openOldDB(appName,prefix,dbname, - openflags, &handle->version); + handle->db = openOldDB(appName,prefix,dbname, openflags); + verifyVersion(handle); if (handle->db == NULL) { goto loser; } @@ -1083,14 +1140,7 @@ loser: if ( dbname ) PORT_Free( dbname ); PORT_SetError(SEC_ERROR_BAD_DATABASE); - - if ( handle->db ) { - keydb_Close(handle->db); - } - if ( handle->updatedb ) { - keydb_Close(handle->updatedb); - } - PORT_Free(handle); + nsslowkey_CloseKeyDB(handle); return NULL; } @@ -1102,8 +1152,11 @@ nsslowkey_CloseKeyDB(NSSLOWKEYDBHandle *handle) { if (handle != NULL) { if (handle->db != NULL) { - keydb_Close(handle->db); + keydb_Close(handle); } + if (handle->updatedb) { + handle->updatedb->close(handle->updatedb); + } if (handle->dbname) PORT_Free(handle->dbname); if (handle->appname) PORT_Free(handle->appname); if (handle->global_salt) { @@ -1143,14 +1196,14 @@ nsslowkey_DeleteKey(NSSLOWKEYDBHandle *handle, SECItem *pubkey) namekey.size = pubkey->len; /* delete it from the database */ - ret = keydb_Del(handle->db, &namekey, 0); + ret = keydb_Del(handle, &namekey, 0); if ( ret ) { PORT_SetError(SEC_ERROR_BAD_DATABASE); return(SECFailure); } /* sync the database */ - ret = keydb_Sync(handle->db, 0); + ret = keydb_Sync(handle, 0); if ( ret ) { PORT_SetError(SEC_ERROR_BAD_DATABASE); return(SECFailure); @@ -1195,7 +1248,7 @@ nsslowkey_KeyForIDExists(NSSLOWKEYDBHandle *handle, SECItem *id) namekey.data = (char *)id->data; namekey.size = id->len; - status = keydb_Get(handle->db, &namekey, &dummy, 0); + status = keydb_Get(handle, &namekey, &dummy, 0); if ( status ) { return PR_FALSE; } @@ -1253,7 +1306,7 @@ nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle, NSSLOWCERTCertificate *cer namekey.size = sizeof(buf); } - status = keydb_Get(handle->db, &namekey, &dummy, 0); + status = keydb_Get(handle, &namekey, &dummy, 0); /* some databases have the key stored as a signed value */ if (status) { unsigned char *buf = (unsigned char *)PORT_Alloc(namekey.size+1); @@ -1262,7 +1315,7 @@ nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle, NSSLOWCERTCertificate *cer buf[0] = 0; namekey.data = buf; namekey.size ++; - status = keydb_Get(handle->db, &namekey, &dummy, 0); + status = keydb_Get(handle, &namekey, &dummy, 0); PORT_Free(buf); } } @@ -1290,12 +1343,12 @@ nsslowkey_HasKeyDBPassword(NSSLOWKEYDBHandle *handle) checkkey.data = KEYDB_PW_CHECK_STRING; checkkey.size = KEYDB_PW_CHECK_LEN; - ret = keydb_Get(handle->db, &checkkey, &checkdata, 0 ); + ret = keydb_Get(handle, &checkkey, &checkdata, 0 ); if ( ret ) { /* see if this was an updated DB first */ checkkey.data = KEYDB_FAKE_PW_CHECK_STRING; checkkey.size = KEYDB_FAKE_PW_CHECK_LEN; - ret = keydb_Get(handle->db, &checkkey, &checkdata, 0 ); + ret = keydb_Get(handle, &checkkey, &checkdata, 0 ); if ( ret ) { return(SECFailure); } @@ -2423,7 +2476,7 @@ nsslowkey_CheckKeyDBPassword(NSSLOWKEYDBHandle *handle, SECItem *pwitem) if ( dbkey == NULL ) { checkkey.data = KEYDB_FAKE_PW_CHECK_STRING; checkkey.size = KEYDB_FAKE_PW_CHECK_LEN; - ret = keydb_Get(handle->db, &checkkey, &checkdata, 0 ); + ret = keydb_Get(handle, &checkkey, &checkdata, 0 ); if (ret) { goto loser; } @@ -2568,7 +2621,7 @@ ChangeKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle, } /* delete the old record */ - ret = keydb_Del(handle->db, &node->key, 0); + ret = keydb_Del(handle, &node->key, 0); if ( ret ) { PORT_SetError(SEC_ERROR_BAD_DATABASE); rv = SECFailure; @@ -2685,7 +2738,7 @@ nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle) return SECFailure; } - keydb_Close(handle->db); + keydb_Close(handle); if (handle->appname) { handle->db= rdbopen(handle->appname, handle->dbname, "key", NO_CREATE, NULL); @@ -2717,17 +2770,19 @@ nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle) done: /* sync the database */ - ret = keydb_Sync(handle->db, 0); + ret = keydb_Sync(handle, 0); db_InitComplete(handle->db); return (errors == 0 ? SECSuccess : SECFailure); } static int -keydb_Get(DB *db, DBT *key, DBT *data, unsigned int flags) +keydb_Get(NSSLOWKEYDBHandle *kdb, DBT *key, DBT *data, unsigned int flags) { PRStatus prstat; int ret; + PRLock *kdbLock = kdb->lock; + DB *db = kdb->db; PORT_Assert(kdbLock != NULL); PZ_Lock(kdbLock); @@ -2740,10 +2795,12 @@ keydb_Get(DB *db, DBT *key, DBT *data, unsigned int flags) } static int -keydb_Put(DB *db, DBT *key, DBT *data, unsigned int flags) +keydb_Put(NSSLOWKEYDBHandle *kdb, DBT *key, DBT *data, unsigned int flags) { PRStatus prstat; int ret = 0; + PRLock *kdbLock = kdb->lock; + DB *db = kdb->db; PORT_Assert(kdbLock != NULL); PZ_Lock(kdbLock); @@ -2756,10 +2813,12 @@ keydb_Put(DB *db, DBT *key, DBT *data, unsigned int flags) } static int -keydb_Sync(DB *db, unsigned int flags) +keydb_Sync(NSSLOWKEYDBHandle *kdb, unsigned int flags) { PRStatus prstat; int ret; + PRLock *kdbLock = kdb->lock; + DB *db = kdb->db; PORT_Assert(kdbLock != NULL); PZ_Lock(kdbLock); @@ -2772,10 +2831,12 @@ keydb_Sync(DB *db, unsigned int flags) } static int -keydb_Del(DB *db, DBT *key, unsigned int flags) +keydb_Del(NSSLOWKEYDBHandle *kdb, DBT *key, unsigned int flags) { PRStatus prstat; int ret; + PRLock *kdbLock = kdb->lock; + DB *db = kdb->db; PORT_Assert(kdbLock != NULL); PZ_Lock(kdbLock); @@ -2788,10 +2849,12 @@ keydb_Del(DB *db, DBT *key, unsigned int flags) } static int -keydb_Seq(DB *db, DBT *key, DBT *data, unsigned int flags) +keydb_Seq(NSSLOWKEYDBHandle *kdb, DBT *key, DBT *data, unsigned int flags) { PRStatus prstat; int ret; + PRLock *kdbLock = kdb->lock; + DB *db = kdb->db; PORT_Assert(kdbLock != NULL); PZ_Lock(kdbLock); @@ -2804,9 +2867,11 @@ keydb_Seq(DB *db, DBT *key, DBT *data, unsigned int flags) } static void -keydb_Close(DB *db) +keydb_Close(NSSLOWKEYDBHandle *kdb) { PRStatus prstat; + PRLock *kdbLock = kdb->lock; + DB *db = kdb->db; PORT_Assert(kdbLock != NULL); PZ_Lock(kdbLock); diff --git a/security/nss/lib/softoken/keydbi.h b/security/nss/lib/softoken/keydbi.h index 1c9c2699a..f7f427266 100644 --- a/security/nss/lib/softoken/keydbi.h +++ b/security/nss/lib/softoken/keydbi.h @@ -56,6 +56,8 @@ struct NSSLOWKEYDBHandleStr { char *appname; /* multiaccess app name */ char *dbname; /* name of the openned DB */ PRBool readOnly; /* is the DB read only */ + PRLock *lock; + PRInt32 ref; /* reference count */ }; /* diff --git a/security/nss/lib/softoken/lowcert.c b/security/nss/lib/softoken/lowcert.c index 01659aba2..cb048307d 100644 --- a/security/nss/lib/softoken/lowcert.c +++ b/security/nss/lib/softoken/lowcert.c @@ -50,6 +50,7 @@ #include "pcert.h" #include "secasn1.h" #include "secoid.h" +#include "secerr.h" #ifdef NSS_ENABLE_ECC extern SECStatus EC_FillParams(PRArenaPool *arena, @@ -362,21 +363,41 @@ nsslowcert_IsNewer(NSSLOWCERTCertificate *certa, NSSLOWCERTCertificate *certb) #define SOFT_DEFAULT_CHUNKSIZE 2048 - static SECStatus -nsslowcert_KeyFromIssuerAndSN(PRArenaPool *arena, SECItem *issuer, SECItem *sn, - SECItem *key) +nsslowcert_KeyFromIssuerAndSN(PRArenaPool *arena, + SECItem *issuer, SECItem *sn, SECItem *key) { unsigned int len = sn->len + issuer->len; - - if (arena) { - key->data = (unsigned char*)PORT_ArenaAlloc(arena, len); - } else { - if (len > key->len) { - key->data = (unsigned char*)PORT_ArenaAlloc(arena, len); - } + if (!arena) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + goto loser; } + key->data = (unsigned char*)PORT_ArenaAlloc(arena, len); + if ( !key->data ) { + goto loser; + } + + key->len = len; + /* copy the serialNumber */ + PORT_Memcpy(key->data, sn->data, sn->len); + + /* copy the issuer */ + PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len); + + return(SECSuccess); + +loser: + return(SECFailure); +} + +static SECStatus +nsslowcert_KeyFromIssuerAndSNStatic(unsigned char *space, + int spaceLen, SECItem *issuer, SECItem *sn, SECItem *key) +{ + unsigned int len = sn->len + issuer->len; + + key->data = pkcs11_allocStaticData(len, space, spaceLen); if ( !key->data ) { goto loser; } @@ -428,12 +449,12 @@ nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, char *nickname) cert->subjectKeyID.len = 0; cert->dbEntry = NULL; cert ->trust = NULL; + cert ->dbhandle = NULL; /* generate and save the database key for the cert */ - cert->certKey.data = cert->certKeySpace; - cert->certKey.len = sizeof(cert->certKeySpace); - rv = nsslowcert_KeyFromIssuerAndSN(NULL, &cert->derIssuer, - &cert->serialNumber, &cert->certKey); + rv = nsslowcert_KeyFromIssuerAndSNStatic(cert->certKeySpace, + sizeof(cert->certKeySpace), &cert->derIssuer, + &cert->serialNumber, &cert->certKey); if ( rv ) { goto loser; } diff --git a/security/nss/lib/softoken/lowpbe.c b/security/nss/lib/softoken/lowpbe.c index 02ba3dfdb..81a0cb06b 100644 --- a/security/nss/lib/softoken/lowpbe.c +++ b/security/nss/lib/softoken/lowpbe.c @@ -249,7 +249,7 @@ nsspkcs5_PFXPBE(const SECHashObject *hashObj, NSSPKCS5PBEParameter *pbe_param, loser: if (state != NULL) PORT_ZFree(state, state_len); - HMAC_Destroy(cx); + HMAC_Destroy(cx, PR_TRUE); if(rv != SECSuccess) { SECITEM_ZfreeItem(ret_bits, PR_TRUE); @@ -363,7 +363,7 @@ nsspkcs5_PBKFD2_F(const SECHashObject *hashobj, SECItem *pwitem, SECItem *salt, } loser: if (cx) { - HMAC_DestroyContext(cx); + HMAC_DestroyContext(cx, PR_TRUE); } if (last) { PORT_ZFree(last,reaLastLength); @@ -587,7 +587,7 @@ nsspkcs5_ComputeKeyAndIV(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, iv->len = pbe_param->ivLen; } - hashObj = &SECRawHashObjects[pbe_param->hashType]; + hashObj = HASH_GetRawHashObject(pbe_param->hashType); switch (pbe_param->pbeType) { case NSSPKCS5_PBKDF1: hash = nsspkcs5_PBKDF1Extended(hashObj,pbe_param,pwitem,faulty3DES); diff --git a/security/nss/lib/softoken/manifest.mn b/security/nss/lib/softoken/manifest.mn index 57f2b273b..52d1f75cd 100644 --- a/security/nss/lib/softoken/manifest.mn +++ b/security/nss/lib/softoken/manifest.mn @@ -58,10 +58,10 @@ EXPORTS = \ PRIVATE_EXPORTS = \ pk11pars.h \ + pkcs11ni.h \ $(NULL) CSRCS = \ - alghmac.c \ dbinit.c \ dbmshim.c \ ecdecode.c \ @@ -77,7 +77,6 @@ CSRCS = \ pkcs11.c \ pkcs11c.c \ pkcs11u.c \ - rawhash.c \ rsawrapr.c \ softkver.c \ tlsprf.c \ diff --git a/security/nss/lib/softoken/pcert.h b/security/nss/lib/softoken/pcert.h index 15b268433..a808373d8 100644 --- a/security/nss/lib/softoken/pcert.h +++ b/security/nss/lib/softoken/pcert.h @@ -237,6 +237,9 @@ void pkcs11_freeStaticData(unsigned char *data, unsigned char *space); unsigned char * +pkcs11_allocStaticData(int datalen, unsigned char *space, int spaceLen); + +unsigned char * pkcs11_copyStaticData(unsigned char *data, int datalen, unsigned char *space, int spaceLen); NSSLOWCERTCertificate * diff --git a/security/nss/lib/softoken/pcertdb.c b/security/nss/lib/softoken/pcertdb.c index 80faa7d84..4a7706378 100644 --- a/security/nss/lib/softoken/pcertdb.c +++ b/security/nss/lib/softoken/pcertdb.c @@ -60,6 +60,7 @@ #include "plhash.h" #include "cdbhdl.h" +#include "pkcs11i.h" /* forward declaration */ NSSLOWCERTCertificate * @@ -389,16 +390,24 @@ pkcs11_freeStaticData (unsigned char *data, unsigned char *space) } unsigned char * -pkcs11_copyStaticData(unsigned char *data, int len, - unsigned char *space, int spaceLen) +pkcs11_allocStaticData(int len, unsigned char *space, int spaceLen) { - unsigned char *copy = NULL; + unsigned char *data = NULL; if (len <= spaceLen) { - copy = space; + data = space; } else { - copy = (unsigned char *) PORT_Alloc(len); + data = (unsigned char *) PORT_Alloc(len); } + + return data; +} + +unsigned char * +pkcs11_copyStaticData(unsigned char *data, int len, + unsigned char *space, int spaceLen) +{ + unsigned char *copy = pkcs11_allocStaticData(len, space, spaceLen); if (copy) { PORT_Memcpy(copy,data,len); } @@ -3386,12 +3395,15 @@ AddCertToPermDB(NSSLOWCERTCertDBHandle *handle, NSSLOWCERTCertificate *cert, state = 2; - cert->dbhandle = handle; + /* "Change" handles if necessary */ + if (cert->dbhandle) { + sftk_freeCertDB(cert->dbhandle); + } + cert->dbhandle = nsslowcert_reference(handle); /* add to or create new subject entry */ if ( subjectEntry ) { /* REWRITE BASED ON SUBJECT ENTRY */ - cert->dbhandle = handle; rv = AddPermSubjectNode(subjectEntry, cert, nickname); if ( rv != SECSuccess ) { goto loser; @@ -3513,6 +3525,9 @@ UpdateV7DB(NSSLOWCERTCertDBHandle *handle, DB *updatedb) case certDBEntryTypeSubject: case certDBEntryTypeContentVersion: case certDBEntryTypeNickname: + /* smime profiles need entries created after the certs have + * been imported, loop over them in a second run */ + case certDBEntryTypeSMimeProfile: break; case certDBEntryTypeCert: @@ -3560,22 +3575,45 @@ UpdateV7DB(NSSLOWCERTCertDBHandle *handle, DB *updatedb) crlEntry.common.arena = NULL; break; - case certDBEntryTypeSMimeProfile: - smimeEntry.common.version = (unsigned int)dataBuf[0]; - smimeEntry.common.type = entryType; - smimeEntry.common.flags = (unsigned int)dataBuf[2]; - smimeEntry.common.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - rv = DecodeDBSMimeEntry(&smimeEntry,&dbEntry,(char *)dbKey.data); - /* decode entry */ + default: + break; + } + } while ( (* updatedb->seq)(updatedb, &key, &data, R_NEXT) == 0 ); + + /* now loop again updating just the SMimeProfile. */ + ret = (* updatedb->seq)(updatedb, &key, &data, R_FIRST); + + if ( ret ) { + return(SECFailure); + } + + do { + unsigned char *dataBuf = (unsigned char *)data.data; + unsigned char *keyBuf = (unsigned char *)key.data; + dbEntry.data = &dataBuf[SEC_DB_ENTRY_HEADER_LEN]; + dbEntry.len = data.size - SEC_DB_ENTRY_HEADER_LEN; + entryType = (certDBEntryType) keyBuf[0]; + if (entryType != certDBEntryTypeSMimeProfile) { + continue; + } + dbKey.data = &keyBuf[SEC_DB_KEY_HEADER_LEN]; + dbKey.len = key.size - SEC_DB_KEY_HEADER_LEN; + if ((dbEntry.len <= 0) || (dbKey.len <= 0)) { + continue; + } + smimeEntry.common.version = (unsigned int)dataBuf[0]; + smimeEntry.common.type = entryType; + smimeEntry.common.flags = (unsigned int)dataBuf[2]; + smimeEntry.common.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + /* decode entry */ + rv = DecodeDBSMimeEntry(&smimeEntry,&dbEntry,(char *)dbKey.data); + if (rv == SECSuccess) { nsslowcert_UpdateSMimeProfile(handle, smimeEntry.emailAddr, &smimeEntry.subjectName, &smimeEntry.smimeOptions, &smimeEntry.optionsDate); - PORT_FreeArena(smimeEntry.common.arena, PR_FALSE); - smimeEntry.common.arena = NULL; - break; - default: - break; } + PORT_FreeArena(smimeEntry.common.arena, PR_FALSE); + smimeEntry.common.arena = NULL; } while ( (* updatedb->seq)(updatedb, &key, &data, R_NEXT) == 0 ); (* updatedb->close)(updatedb); @@ -4029,17 +4067,6 @@ openNewCertDB(const char *appName, const char *prefix, const char *certdbname, } /* Verify version number; */ - - if (appName) { - updatedb = dbsopen(certdbname, NO_RDONLY, 0600, DB_HASH, 0); - if (updatedb) { - rv = UpdateV8DB(handle, updatedb); - db_FinishTransaction(handle->permCertDB,PR_FALSE); - db_InitComplete(handle->permCertDB); - return(rv); - } - } - versionEntry = NewDBVersionEntry(0); if ( versionEntry == NULL ) { rv = SECFailure; @@ -4056,7 +4083,10 @@ openNewCertDB(const char *appName, const char *prefix, const char *certdbname, /* rv must already be Success here because of previous if statement */ /* try to upgrade old db here */ - if ((updatedb = nsslowcert_openolddb(namecb,cbarg,7)) != NULL) { + if (appName && + (updatedb = dbsopen(certdbname, NO_RDONLY, 0600, DB_HASH, 0)) != NULL) { + rv = UpdateV8DB(handle, updatedb); + } else if ((updatedb = nsslowcert_openolddb(namecb,cbarg,7)) != NULL) { rv = UpdateV7DB(handle, updatedb); } else if ((updatedb = nsslowcert_openolddb(namecb,cbarg,6)) != NULL) { rv = UpdateV6DB(handle, updatedb); @@ -4295,7 +4325,7 @@ DecodeACert(NSSLOWCERTCertDBHandle *handle, certDBEntryCert *entry) goto loser; } - cert->dbhandle = handle; + cert->dbhandle = nsslowcert_reference(handle); cert->dbEntry = entry; cert->trust = &entry->trust; @@ -4349,7 +4379,7 @@ DecodeTrustEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryCert *entry, if (trust == NULL) { return trust; } - trust->dbhandle = handle; + trust->dbhandle = nsslowcert_reference(handle); trust->dbEntry = entry; trust->dbKey.data = pkcs11_copyStaticData(dbKey->data,dbKey->len, trust->dbKeySpace, sizeof(trust->dbKeySpace)); @@ -4983,6 +5013,9 @@ DestroyCertificate(NSSLOWCERTCertificate *cert, PRBool lockdb) */ if ( lockdb && handle ) { nsslowcert_LockDB(handle); + /* keep a reference until we unlock, so handle won't disappear + * before we are through with it */ + nsslowcert_reference(handle); } nsslowcert_LockCertRefCount(cert); @@ -5016,11 +5049,15 @@ DestroyCertificate(NSSLOWCERTCertificate *cert, PRBool lockdb) certListHead = cert; } nsslowcert_UnlockFreeList(); + if (handle) { + sftk_freeCertDB(handle); + } cert = NULL; } if ( lockdb && handle ) { nsslowcert_UnlockDB(handle); + sftk_freeCertDB(handle); } } diff --git a/security/nss/lib/softoken/pk11db.c b/security/nss/lib/softoken/pk11db.c index 391803329..c60e87780 100644 --- a/security/nss/lib/softoken/pk11db.c +++ b/security/nss/lib/softoken/pk11db.c @@ -120,9 +120,9 @@ secmod_parseTokens(char *tokenParams, sftk_parameters *parsed) tokenIndex += next; tokens[i].slotID = secmod_argDecodeNumber(name); - tokens[i].readOnly = PR_TRUE; - tokens[i].noCertDB = PR_TRUE; - tokens[i].noKeyDB = PR_TRUE; + tokens[i].readOnly = PR_FALSE; + tokens[i].noCertDB = PR_FALSE; + tokens[i].noKeyDB = PR_FALSE; if (!secmod_argIsBlank(*tokenIndex)) { char *args = secmod_argFetchValue(tokenIndex,&next); tokenIndex += next; @@ -167,8 +167,8 @@ secmod_parseParameters(char *param, sftk_parameters *parsed, PRBool isFIPS) SECMOD_HANDLE_STRING_ARG(index,slotdes,"cryptoSlotDescription=",;) SECMOD_HANDLE_STRING_ARG(index,pslotdes,"dbSlotDescription=",;) SECMOD_HANDLE_STRING_ARG(index,fslotdes,"FIPSSlotDescription=",;) - SECMOD_HANDLE_STRING_ARG(index,minPW,"FIPSTokenDescription=",;) - SECMOD_HANDLE_STRING_ARG(index,tmp,"minPWLen=",;) + SECMOD_HANDLE_STRING_ARG(index,fpslotdes,"FIPSTokenDescription=",;) + SECMOD_HANDLE_STRING_ARG(index,minPW,"minPWLen=",;) SECMOD_HANDLE_STRING_ARG(index,tmp,"flags=", if(tmp) { secmod_parseFlags(param,parsed); PORT_Free(tmp); }) @@ -445,10 +445,10 @@ secmod_EncodeData(DBT *data, char * module) encoded->isCritical = (unsigned char) (secmod_argHasFlag("flags","critical",nss) ? 1 : 0); - order = secmod_argReadLong("trustOrder", nss, SFTK_DEFAULT_TRUST_ORDER, + order = secmod_argReadLong("trustOrder", nss, SECMOD_DEFAULT_TRUST_ORDER, NULL); SECMOD_PUTLONG(encoded->trustOrder,order); - order = secmod_argReadLong("cipherOrder", nss, SFTK_DEFAULT_CIPHER_ORDER, + order = secmod_argReadLong("cipherOrder", nss, SECMOD_DEFAULT_CIPHER_ORDER, NULL); SECMOD_PUTLONG(encoded->cipherOrder,order); @@ -551,8 +551,8 @@ secmod_DecodeData(char *defParams, DBT *data, PRBool *retInternal) unsigned long slotID; unsigned long defaultFlags; unsigned long timeout; - unsigned long trustOrder =SFTK_DEFAULT_TRUST_ORDER; - unsigned long cipherOrder =SFTK_DEFAULT_CIPHER_ORDER; + unsigned long trustOrder =SECMOD_DEFAULT_TRUST_ORDER; + unsigned long cipherOrder =SECMOD_DEFAULT_CIPHER_ORDER; unsigned short len; unsigned short namesOffset = 0; /* start of the names block */ unsigned long namesRunningOffset; /* offset to name we are diff --git a/security/nss/lib/softoken/pk11pars.h b/security/nss/lib/softoken/pk11pars.h index 6e01b7ffb..ebb1d1b2b 100644 --- a/security/nss/lib/softoken/pk11pars.h +++ b/security/nss/lib/softoken/pk11pars.h @@ -64,8 +64,8 @@ struct secmodargSlotFlagTable { unsigned long value; }; -#define SFTK_DEFAULT_CIPHER_ORDER 0 -#define SFTK_DEFAULT_TRUST_ORDER 50 +#define SECMOD_DEFAULT_CIPHER_ORDER 0 +#define SECMOD_DEFAULT_TRUST_ORDER 50 #define SECMOD_ARG_ENTRY(arg,flag) \ @@ -194,14 +194,21 @@ secmod_argFetchValue(char *string, int *pcount) char *end = secmod_argFindEnd(string); char *retString, *copyString; PRBool lastEscape = PR_FALSE; + int len; - *pcount = (end - string)+1; + len = end - string; + if (len == 0) { + *pcount = 0; + return NULL; + } - if (*pcount == 0) return NULL; + copyString = retString = (char *)PORT_Alloc(len+1); - copyString = retString = (char *)PORT_Alloc(*pcount); + if (*end) len++; + *pcount = len; if (retString == NULL) return NULL; + if (secmod_argIsQuote(*string)) string++; for (; string < end; string++) { if (secmod_argIsEscape(*string) && !lastEscape) { @@ -815,9 +822,9 @@ secmod_mkNSS(char **slotStrings, int slotCount, PRBool internal, PRBool isFIPS, ciphers = secmod_mkCipherFlags(ssl0, ssl1); trustOrderPair=secmod_formatIntPair("trustOrder",trustOrder, - SFTK_DEFAULT_TRUST_ORDER); + SECMOD_DEFAULT_TRUST_ORDER); cipherOrderPair=secmod_formatIntPair("cipherOrder",cipherOrder, - SFTK_DEFAULT_CIPHER_ORDER); + SECMOD_DEFAULT_CIPHER_ORDER); slotPair=secmod_formatPair("slotParams",slotParams,'{'); /* } */ if (slotParams) PORT_Free(slotParams); cipherPair=secmod_formatPair("ciphers",ciphers,'\''); diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c index f9090a925..10a7bcfb7 100644 --- a/security/nss/lib/softoken/pkcs11.c +++ b/security/nss/lib/softoken/pkcs11.c @@ -55,6 +55,7 @@ #include "secitem.h" #include "pkcs11.h" #include "pkcs11i.h" +#include "pkcs11p.h" #include "softoken.h" #include "lowkeyi.h" #include "blapi.h" @@ -81,6 +82,12 @@ static char manufacturerID_space[33]; static char *libraryDescription = "NSS Internal Crypto Services "; static char libraryDescription_space[33]; +/* + * In FIPS mode, we disallow login attempts for 1 second after a login + * failure so that there are at most 60 login attempts per minute. + */ +static PRIntervalTime loginWaitTime; + #define __PASTE(x,y) x##y /* @@ -267,7 +274,7 @@ static const struct mechanismList mechanisms[] = { {CKM_RSA_PKCS_KEY_PAIR_GEN,{RSA_MIN_MODULUS_BITS,CK_MAX, CKF_GENERATE_KEY_PAIR},PR_TRUE}, {CKM_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX, - CKF_DUZ_IT_ALL}, PR_TRUE}, + CKF_DUZ_IT_ALL}, PR_TRUE}, #ifdef SFTK_RSA9796_SUPPORTED {CKM_RSA_9796, {RSA_MIN_MODULUS_BITS,CK_MAX, CKF_DUZ_IT_ALL}, PR_TRUE}, @@ -523,7 +530,7 @@ sftk_configure(const char *man, const char *libdes) /* * see if the key DB password is enabled */ -PRBool +static PRBool sftk_hasNullPassword(NSSLOWKEYDBHandle *keydb,SECItem **pwitem) { PRBool pwenabled; @@ -659,8 +666,10 @@ sftk_handleCertObject(SFTKSession *session,SFTKObject *object) char *email = NULL; SECStatus rv; PRBool inDB = PR_TRUE; + NSSLOWCERTCertDBHandle *certHandle = sftk_getCertDB(slot); + NSSLOWKEYDBHandle *keyHandle = NULL; - if (slot->certDB == NULL) { + if (certHandle == NULL) { return CKR_TOKEN_WRITE_PROTECTED; } @@ -674,25 +683,31 @@ sftk_handleCertObject(SFTKSession *session,SFTKObject *object) label = sftk_getString(object,CKA_LABEL); - cert = nsslowcert_FindCertByDERCert(slot->certDB, &derCert); - if (cert == NULL) { + cert = nsslowcert_FindCertByDERCert(certHandle, &derCert); + if (cert == NULL) { cert = nsslowcert_DecodeDERCertificate(&derCert, label); inDB = PR_FALSE; } if (cert == NULL) { if (label) PORT_Free(label); sftk_FreeAttribute(attribute); + sftk_freeCertDB(certHandle); return CKR_ATTRIBUTE_VALUE_INVALID; } - if (slot->keyDB && nsslowkey_KeyForCertExists(slot->keyDB,cert)) { - trust = &userTrust; + keyHandle = sftk_getKeyDB(slot); + if (keyHandle) { + if (nsslowkey_KeyForCertExists(keyHandle,cert)) { + trust = &userTrust; + } + sftk_freeKeyDB(keyHandle); } + if (!inDB) { if (!trust) trust = &defTrust; - rv = nsslowcert_AddPermCert(slot->certDB, cert, label, trust); + rv = nsslowcert_AddPermCert(certHandle, cert, label, trust); } else { - rv = trust ? nsslowcert_ChangeCertTrust(slot->certDB,cert,trust) : + rv = trust ? nsslowcert_ChangeCertTrust(certHandle,cert,trust) : SECSuccess; } @@ -700,6 +715,7 @@ sftk_handleCertObject(SFTKSession *session,SFTKObject *object) sftk_FreeAttribute(attribute); if (rv != SECSuccess) { + sftk_freeCertDB(certHandle); nsslowcert_DestroyCertificate(cert); return CKR_DEVICE_ERROR; } @@ -711,15 +727,16 @@ sftk_handleCertObject(SFTKSession *session,SFTKObject *object) if (email) { certDBEntrySMime *entry; - entry = nsslowcert_ReadDBSMimeEntry(slot->certDB,email); + entry = nsslowcert_ReadDBSMimeEntry(certHandle,email); if (!entry) { - nsslowcert_SaveSMimeProfile(slot->certDB, email, + nsslowcert_SaveSMimeProfile(certHandle, email, &cert->derSubject, NULL, NULL); } else { nsslowcert_DestroyDBEntry((certDBEntry *)entry); } PORT_Free(email); } + sftk_freeCertDB(certHandle); object->handle=sftk_mkHandle(slot,&cert->certKey,SFTK_TOKEN_TYPE_CERT); nsslowcert_DestroyCertificate(cert); } @@ -792,11 +809,12 @@ sftk_handleTrustObject(SFTKSession *session,SFTKObject *object) CK_BBOOL stepUp; NSSLOWCERTCertTrust dbTrust = { 0 }; SECStatus rv; + NSSLOWCERTCertDBHandle *certHandle = sftk_getCertDB(slot); - - if (slot->certDB == NULL) { + if (certHandle == NULL) { return CKR_TOKEN_WRITE_PROTECTED; } + issuer = sftk_FindAttribute(object,CKA_ISSUER); PORT_Assert(issuer); issuerSN.derIssuer.data = (unsigned char *)issuer->attrib.pValue; @@ -807,11 +825,12 @@ sftk_handleTrustObject(SFTKSession *session,SFTKObject *object) issuerSN.serialNumber.data = (unsigned char *)serial->attrib.pValue; issuerSN.serialNumber.len = serial->attrib.ulValueLen ; - cert = nsslowcert_FindCertByIssuerAndSN(slot->certDB,&issuerSN); + cert = nsslowcert_FindCertByIssuerAndSN(certHandle,&issuerSN); sftk_FreeAttribute(serial); sftk_FreeAttribute(issuer); if (cert == NULL) { + sftk_freeCertDB(certHandle); return CKR_ATTRIBUTE_VALUE_INVALID; } @@ -873,9 +892,10 @@ sftk_handleTrustObject(SFTKSession *session,SFTKObject *object) dbTrust.sslFlags |= CERTDB_GOVT_APPROVED_CA; } - rv = nsslowcert_ChangeCertTrust(slot->certDB,cert,&dbTrust); + rv = nsslowcert_ChangeCertTrust(certHandle,cert,&dbTrust); object->handle=sftk_mkHandle(slot,&cert->certKey,SFTK_TOKEN_TYPE_TRUST); nsslowcert_DestroyCertificate(cert); + sftk_freeCertDB(certHandle); if (rv != SECSuccess) { return CKR_DEVICE_ERROR; } @@ -912,9 +932,12 @@ sftk_handleSMimeObject(SFTKSession *session,SFTKObject *object) char *email = NULL; SFTKAttribute *subject,*profile,*time; SECStatus rv; + NSSLOWCERTCertDBHandle *certHandle; PORT_Assert(slot); - if (slot->certDB == NULL) { + certHandle = sftk_getCertDB(slot); + + if (certHandle == NULL) { return CKR_TOKEN_WRITE_PROTECTED; } @@ -947,9 +970,9 @@ sftk_handleSMimeObject(SFTKSession *session,SFTKObject *object) email = sftk_getString(object,CKA_NETSCAPE_EMAIL); /* Store CRL by SUBJECT */ - rv = nsslowcert_SaveSMimeProfile(slot->certDB, email, &derSubj, + rv = nsslowcert_SaveSMimeProfile(certHandle, email, &derSubj, pRawProfile,pRawTime); - + sftk_freeCertDB(certHandle); sftk_FreeAttribute(subject); if (profile) sftk_FreeAttribute(profile); if (time) sftk_FreeAttribute(time); @@ -994,9 +1017,12 @@ sftk_handleCrlObject(SFTKSession *session,SFTKObject *object) char *url = NULL; SFTKAttribute *subject,*crl; SECStatus rv; + NSSLOWCERTCertDBHandle *certHandle; PORT_Assert(slot); - if (slot->certDB == NULL) { + certHandle = sftk_getCertDB(slot); + + if (certHandle == NULL) { return CKR_TOKEN_WRITE_PROTECTED; } @@ -1017,7 +1043,8 @@ sftk_handleCrlObject(SFTKSession *session,SFTKObject *object) isKRL = sftk_isTrue(object,CKA_NETSCAPE_KRL); /* Store CRL by SUBJECT */ - rv = nsslowcert_AddCrl(slot->certDB, &derCrl, &derSubj, url, isKRL); + rv = nsslowcert_AddCrl(certHandle, &derCrl, &derSubj, url, isKRL); + sftk_freeCertDB(certHandle); if (url) { PORT_Free(url); @@ -1156,16 +1183,18 @@ sftk_handlePublicKeyObject(SFTKSession *session, SFTKObject *object, SFTKSlot *slot = session->slot; NSSLOWKEYPrivateKey *priv; SECItem pubKey; + NSSLOWKEYDBHandle *keyHandle = NULL; crv = sftk_Attribute2SSecItem(NULL,&pubKey,object,pubKeyAttr); if (crv != CKR_OK) return crv; PORT_Assert(pubKey.data); - if (slot->keyDB == NULL) { + keyHandle = sftk_getKeyDB(slot); + if (keyHandle == NULL) { PORT_Free(pubKey.data); return CKR_TOKEN_WRITE_PROTECTED; } - if (slot->keyDB->version != 3) { + if (keyHandle->version != 3) { unsigned char buf[SHA1_LENGTH]; SHA1_HashBuf(buf,pubKey.data,pubKey.len); PORT_Memcpy(pubKey.data,buf,sizeof(buf)); @@ -1173,11 +1202,11 @@ sftk_handlePublicKeyObject(SFTKSession *session, SFTKObject *object, } /* make sure the associated private key already exists */ /* only works if we are logged in */ - priv = nsslowkey_FindKeyByPublicKey(slot->keyDB, &pubKey, - slot->password); + priv = nsslowkey_FindKeyByPublicKey(keyHandle, &pubKey, slot->password); + sftk_freeKeyDB(keyHandle); if (priv == NULL) { PORT_Free(pubKey.data); - return CKR_ATTRIBUTE_VALUE_INVALID; + return crv; } nsslowkey_DestroyPrivateKey(priv); @@ -1315,9 +1344,11 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE NSSLOWKEYPrivateKey *privKey; char *label; SECStatus rv = SECSuccess; + CK_RV crv = CKR_DEVICE_ERROR; SECItem pubKey; + NSSLOWKEYDBHandle *keyHandle = sftk_getKeyDB(slot); - if (slot->keyDB == NULL) { + if (keyHandle == NULL) { return CKR_TOKEN_WRITE_PROTECTED; } @@ -1327,11 +1358,11 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE crv = sftk_Attribute2SSecItem(NULL,&pubKey,object,CKA_NETSCAPE_DB); if (crv != CKR_OK) { - if (label) PORT_Free(label); - nsslowkey_DestroyPrivateKey(privKey); - return CKR_TEMPLATE_INCOMPLETE; + crv = CKR_TEMPLATE_INCOMPLETE; + rv = SECFailure; + goto fail; } - if (slot->keyDB->version != 3) { + if (keyHandle->version != 3) { unsigned char buf[SHA1_LENGTH]; SHA1_HashBuf(buf,pubKey.data,pubKey.len); PORT_Memcpy(pubKey.data,buf,sizeof(buf)); @@ -1344,28 +1375,24 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE goto fail; } } - rv = nsslowkey_StoreKeyByPublicKey(object->slot->keyDB, - privKey, &pubKey, label, object->slot->password); + rv = nsslowkey_StoreKeyByPublicKey(keyHandle, privKey, &pubKey, + label, slot->password); fail: + sftk_freeKeyDB(keyHandle); if (label) PORT_Free(label); object->handle = sftk_mkHandle(slot,&pubKey,SFTK_TOKEN_TYPE_PRIV); if (pubKey.data) PORT_Free(pubKey.data); nsslowkey_DestroyPrivateKey(privKey); - if (rv != SECSuccess) return CKR_DEVICE_ERROR; + if (rv != SECSuccess) return crv; } else { object->objectInfo = sftk_mkPrivKey(object,key_type,&crv); if (object->objectInfo == NULL) return crv; object->infoFree = (SFTKFree) nsslowkey_DestroyPrivateKey; /* now NULL out the sensitive attributes */ - if (sftk_isTrue(object,CKA_SENSITIVE)) { - sftk_nullAttribute(object,CKA_PRIVATE_EXPONENT); - sftk_nullAttribute(object,CKA_PRIME_1); - sftk_nullAttribute(object,CKA_PRIME_2); - sftk_nullAttribute(object,CKA_EXPONENT_1); - sftk_nullAttribute(object,CKA_EXPONENT_2); - sftk_nullAttribute(object,CKA_COEFFICIENT); - } + /* remove nulled out attributes for session objects. these only + * applied to rsa private keys anyway (other private keys did not + * get their attributes NULL'ed out */ } return CKR_OK; } @@ -1521,7 +1548,8 @@ sftk_handleSecretKeyObject(SFTKSession *session,SFTKObject *object, CK_KEY_TYPE key_type, PRBool isFIPS) { CK_RV crv; - NSSLOWKEYPrivateKey *privKey = NULL; + NSSLOWKEYPrivateKey *privKey = NULL; + NSSLOWKEYDBHandle *keyHandle = NULL; SECItem pubKey; char *label = NULL; @@ -1535,8 +1563,9 @@ sftk_handleSecretKeyObject(SFTKSession *session,SFTKObject *object, if (sftk_isTrue(object,CKA_TOKEN)) { SFTKSlot *slot = session->slot; SECStatus rv = SECSuccess; + keyHandle = sftk_getKeyDB(slot); - if (slot->keyDB == NULL) { + if (keyHandle == NULL) { return CKR_TOKEN_WRITE_PROTECTED; } @@ -1552,21 +1581,20 @@ sftk_handleSecretKeyObject(SFTKSession *session,SFTKObject *object, PORT_Free(pubKey.data); pubKey.data = NULL; } - crv = sftk_GenerateSecretCKA_ID(slot->keyDB, &pubKey, label); + crv = sftk_GenerateSecretCKA_ID(keyHandle, &pubKey, label); if (crv != CKR_OK) goto loser; crv = sftk_forceAttribute(object, CKA_ID, pubKey.data, pubKey.len); if (crv != CKR_OK) goto loser; } - privKey=sftk_mkSecretKeyRep(object); + privKey = sftk_mkSecretKeyRep(object); if (privKey == NULL) { crv = CKR_HOST_MEMORY; goto loser; } - PORT_Assert(slot->keyDB); - rv = nsslowkey_StoreKeyByPublicKey(slot->keyDB, + rv = nsslowkey_StoreKeyByPublicKey(keyHandle, privKey, &pubKey, label, slot->password); if (rv != SECSuccess) { crv = CKR_DEVICE_ERROR; @@ -1577,6 +1605,7 @@ sftk_handleSecretKeyObject(SFTKSession *session,SFTKObject *object, } loser: + if (keyHandle) sftk_freeKeyDB(keyHandle); if (label) PORT_Free(label); if (privKey) nsslowkey_DestroyPrivateKey(privKey); if (pubKey.data) PORT_Free(pubKey.data); @@ -2094,10 +2123,8 @@ sftk_GetPrivKey(SFTKObject *object,CK_KEY_TYPE key_type, CK_RV *crvp) SFTKTokenObject *to = sftk_narrowToTokenObject(object); PORT_Assert(to); - PORT_Assert(object->slot->keyDB); - priv = nsslowkey_FindKeyByPublicKey(object->slot->keyDB, &to->dbKey, - object->slot->password); - *crvp = priv ? CKR_OK : CKR_DEVICE_ERROR; + priv = sftk_FindKeyByPublicKey(object->slot, &to->dbKey); + *crvp = (priv == NULL) ? CKR_DEVICE_ERROR : CKR_OK; } else { priv = sftk_mkPrivKey(object, key_type, crvp); } @@ -2346,7 +2373,7 @@ static PLHashTable *nscSlotHashTable[2] = {NULL, NULL}; static int sftk_GetModuleIndex(CK_SLOT_ID slotID) { - if ((slotID == FIPS_SLOT_ID) || (slotID > 100)) { + if ((slotID == FIPS_SLOT_ID) || (slotID >= SFTK_MIN_FIPS_USER_SLOT_ID)) { return NSC_FIPS_MODULE; } return NSC_NON_FIPS_MODULE; @@ -2354,12 +2381,18 @@ sftk_GetModuleIndex(CK_SLOT_ID slotID) /* look up a slot structure from the ID (used to be a macro when we only * had two slots) */ +/* if all is true, return the slot even if it has been 'unloaded' */ +/* if all is false, only return the slots which are present */ SFTKSlot * -sftk_SlotFromID(CK_SLOT_ID slotID) +sftk_SlotFromID(CK_SLOT_ID slotID, PRBool all) { + SFTKSlot *slot; int index = sftk_GetModuleIndex(slotID); - return (SFTKSlot *)PL_HashTableLookupConst(nscSlotHashTable[index], + slot = (SFTKSlot *)PL_HashTableLookupConst(nscSlotHashTable[index], (void *)slotID); + /* cleared slots shouldn't 'show up' */ + if (slot && !all && !slot->present) slot = NULL; + return slot; } SFTKSlot * @@ -2372,7 +2405,7 @@ sftk_SlotFromSessionHandle(CK_SESSION_HANDLE handle) return NULL; } - return sftk_SlotFromID(nscSlotList[moduleIndex][slotIDIndex]); + return sftk_SlotFromID(nscSlotList[moduleIndex][slotIDIndex], PR_FALSE); } static CK_RV @@ -2427,13 +2460,19 @@ sftk_RegisterSlot(SFTKSlot *slot, int moduleIndex) return CKR_OK; } +typedef struct sftk_DBsStr { + NSSLOWCERTCertDBHandle *certHandle; + NSSLOWKEYDBHandle *keyHandle; +} sftkDBs; + static SECStatus sftk_set_user(NSSLOWCERTCertificate *cert, SECItem *dummy, void *arg) { - SFTKSlot *slot = (SFTKSlot *)arg; + sftkDBs *param = (sftkDBs *)arg; NSSLOWCERTCertTrust trust = *cert->trust; - if (nsslowkey_KeyForCertExists(slot->keyDB,cert)) { + if (param->keyHandle && + nsslowkey_KeyForCertExists(param->keyHandle,cert)) { trust.sslFlags |= CERTDB_USER; trust.emailFlags |= CERTDB_USER; trust.objectSigningFlags |= CERTDB_USER; @@ -2444,26 +2483,120 @@ sftk_set_user(NSSLOWCERTCertificate *cert, SECItem *dummy, void *arg) } if (PORT_Memcmp(&trust,cert->trust, sizeof (trust)) != 0) { - nsslowcert_ChangeCertTrust(slot->certDB,cert, &trust); + nsslowcert_ChangeCertTrust(param->certHandle, cert, &trust); } /* should check for email address and make sure we have an s/mime profile */ return SECSuccess; } +/* + * this function fixes up old databases that may not have the CERTDB_USER + * flags set correctly. it expects the owner already has references to + * the cert and key handles. + */ static void -sftk_DBVerify(SFTKSlot *slot) +sftk_DBVerify(NSSLOWCERTCertDBHandle *certHandle, NSSLOWKEYDBHandle *keyHandle) { /* walk through all the certs and check to see if there are any * user certs, and make sure there are s/mime profiles for all certs with * email addresses */ - nsslowcert_TraversePermCerts(slot->certDB,sftk_set_user,slot); + sftkDBs param; + param.certHandle = certHandle; + param.keyHandle = keyHandle; + + nsslowcert_TraversePermCerts(certHandle, sftk_set_user, ¶m); return; } -/* forward static declaration. */ -static CK_RV sftk_DestroySlotData(SFTKSlot *slot); + +/* + * ths function has all the common initialization that happens whenever we + * create a new slot or repurpose an old slot (only valid for slotID's 4 + * and greater). + * + * things that are not reinitialized are: + * slotID (can't change) + * slotDescription (can't change once defined) + * the locks and hash tables (difficult to change in running code, and + * unnecessary. hash tables and list are cleared on shutdown, but they + * are cleared in a 'friendly' way). + * session and object ID counters -- so any old sessions and objects in the + * application will get properly notified that the world has changed. + * + * things that are reinitialized: + * database (otherwise what would the point be;). + * state variables related to databases. + * session count stat info. + * tokenDescription. + * + * NOTE: slotID's 4 and greater show up as removable devices. + * + */ +CK_RV +SFTK_SlotReInit(SFTKSlot *slot, + char *configdir,sftk_token_parameters *params, int moduleIndex) +{ + PRBool needLogin = !params->noKeyDB; + CK_RV crv; + + slot->hasTokens = PR_FALSE; + slot->sessionIDConflict = 0; + slot->sessionCount = 0; + slot->rwSessionCount = 0; + slot->needLogin = PR_FALSE; + slot->isLoggedIn = PR_FALSE; + slot->ssoLoggedIn = PR_FALSE; + slot->DB_loaded = PR_FALSE; + slot->certDB = NULL; + slot->keyDB = NULL; + slot->minimumPinLen = 0; + slot->readOnly = params->readOnly; + sftk_setStringName(params->tokdes ? params->tokdes : + sftk_getDefTokName(slot->slotID), slot->tokDescription, + sizeof(slot->tokDescription)); + + if ((!params->noCertDB) || (!params->noKeyDB)) { + NSSLOWCERTCertDBHandle * certHandle = NULL; + NSSLOWKEYDBHandle *keyHandle = NULL; + crv = sftk_DBInit(params->configdir ? params->configdir : configdir, + params->certPrefix, params->keyPrefix, params->readOnly, + params->noCertDB, params->noKeyDB, params->forceOpen, + &certHandle, &keyHandle); + if (crv != CKR_OK) { + goto loser; + } + + if (nsslowcert_needDBVerify(certHandle)) { + sftk_DBVerify(certHandle, keyHandle); + } + slot->certDB = certHandle; + slot->keyDB = keyHandle; + } + if (needLogin) { + /* if the data base is initialized with a null password,remember that */ + slot->needLogin = + (PRBool)!sftk_hasNullPassword(slot->keyDB,&slot->password); + if ((params->minPW >= 0) && (params->minPW <= SFTK_MAX_PIN)) { + slot->minimumPinLen = params->minPW; + } + if ((slot->minimumPinLen == 0) && (params->pwRequired)) { + slot->minimumPinLen = 1; + } + if ((moduleIndex == NSC_FIPS_MODULE) && + (slot->minimumPinLen < FIPS_MIN_PIN)) { + slot->minimumPinLen = FIPS_MIN_PIN; + } + } + + slot->present = PR_TRUE; + return CKR_OK; + +loser: + SFTK_ShutdownSlot(slot); + return crv; +} /* * initialize one of the slot structures. figure out which by the ID @@ -2473,9 +2606,15 @@ SFTK_SlotInit(char *configdir,sftk_token_parameters *params, int moduleIndex) { unsigned int i; CK_SLOT_ID slotID = params->slotID; - SFTKSlot *slot = PORT_ZNew(SFTKSlot); - PRBool needLogin = !params->noKeyDB; - CK_RV crv; + SFTKSlot *slot; + CK_RV crv = CKR_HOST_MEMORY; + + /* + * first we initialize everything that is 'permanent' with this slot. + * that is everything we aren't going to shutdown if we close this slot + * and open it up again with different databases */ + + slot = PORT_ZNew(SFTKSlot); if (slot == NULL) { return CKR_HOST_MEMORY; @@ -2507,6 +2646,9 @@ SFTK_SlotInit(char *configdir,sftk_token_parameters *params, int moduleIndex) slot->objectLock = PZ_NewLock(nssILockObject); if (slot->objectLock == NULL) goto mem_loser; + slot->pwCheckLock = PR_NewLock(); + if (slot->pwCheckLock == NULL) + goto mem_loser; slot->head = PORT_ZNewArray(SFTKSession *, slot->sessHashSize); if (slot->head == NULL) goto mem_loser; @@ -2518,53 +2660,18 @@ SFTK_SlotInit(char *configdir,sftk_token_parameters *params, int moduleIndex) if (slot->tokenHashTable == NULL) goto mem_loser; - slot->password = NULL; - slot->hasTokens = PR_FALSE; slot->sessionIDCount = 0; - slot->sessionIDConflict = 0; - slot->sessionCount = 0; - slot->rwSessionCount = 0; slot->tokenIDCount = 1; - slot->needLogin = PR_FALSE; - slot->isLoggedIn = PR_FALSE; - slot->ssoLoggedIn = PR_FALSE; - slot->DB_loaded = PR_FALSE; slot->slotID = slotID; - slot->certDB = NULL; - slot->keyDB = NULL; - slot->minimumPinLen = 0; - slot->readOnly = params->readOnly; - sftk_setStringName(params->tokdes ? params->tokdes : - sftk_getDefTokName(slotID), slot->tokDescription, - sizeof(slot->tokDescription)); sftk_setStringName(params->slotdes ? params->slotdes : - sftk_getDefSlotName(slotID), slot->slotDescription, + sftk_getDefSlotName(slotID), slot->slotDescription, sizeof(slot->slotDescription)); - if ((!params->noCertDB) || (!params->noKeyDB)) { - crv = sftk_DBInit(params->configdir ? params->configdir : configdir, - params->certPrefix, params->keyPrefix, params->readOnly, - params->noCertDB, params->noKeyDB, params->forceOpen, - &slot->certDB, &slot->keyDB); - if (crv != CKR_OK) { - goto loser; - } - - if (nsslowcert_needDBVerify(slot->certDB)) { - sftk_DBVerify(slot); - } - } - if (needLogin) { - /* if the data base is initialized with a null password,remember that */ - slot->needLogin = - (PRBool)!sftk_hasNullPassword(slot->keyDB,&slot->password); - if (params->minPW <= SFTK_MAX_PIN) { - slot->minimumPinLen = params->minPW; - } - if ((slot->minimumPinLen == 0) && (params->pwRequired) && - (slot->minimumPinLen <= SFTK_MAX_PIN)) { - slot->minimumPinLen = 1; - } + /* call the reinit code to set everything that changes between token + * init calls */ + crv = SFTK_SlotReInit(slot, configdir, params, moduleIndex); + if (crv != CKR_OK) { + goto loser; } crv = sftk_RegisterSlot(slot, moduleIndex); if (crv != CKR_OK) { @@ -2575,77 +2682,167 @@ SFTK_SlotInit(char *configdir,sftk_token_parameters *params, int moduleIndex) mem_loser: crv = CKR_HOST_MEMORY; loser: - sftk_DestroySlotData(slot); + SFTK_DestroySlotData(slot); return crv; } -static PRIntn -sftk_freeHashItem(PLHashEntry* entry, PRIntn index, void *arg) + +static CK_RV sft_CloseAllSession(SFTKSlot *slot) { - SECItem *item = (SECItem *)entry->value; + SECItem *pw = NULL; + SFTKSession *session; + unsigned int i; + /* first log out the card */ + PZ_Lock(slot->slotLock); + pw = slot->password; + slot->isLoggedIn = PR_FALSE; + slot->password = NULL; + PZ_Unlock(slot->slotLock); + if (pw) SECITEM_ZfreeItem(pw, PR_TRUE); - SECITEM_FreeItem(item, PR_TRUE); - return HT_ENUMERATE_NEXT; + /* now close all the current sessions */ + /* NOTE: If you try to open new sessions before NSC_CloseAllSessions + * completes, some of those new sessions may or may not be closed by + * NSC_CloseAllSessions... but any session running when this code starts + * will guarrenteed be close, and no session will be partially closed */ + for (i=0; i < slot->sessHashSize; i++) { + PZLock *lock = SFTK_SESSION_LOCK(slot,i); + do { + PZ_Lock(lock); + session = slot->head[i]; + /* hand deque */ + /* this duplicates function of NSC_close session functions, but + * because we know that we are freeing all the sessions, we can + * do more efficient processing */ + if (session) { + slot->head[i] = session->next; + if (session->next) session->next->prev = NULL; + session->next = session->prev = NULL; + PZ_Unlock(lock); + PZ_Lock(slot->slotLock); + --slot->sessionCount; + PZ_Unlock(slot->slotLock); + if (session->info.flags & CKF_RW_SESSION) { + PR_AtomicDecrement(&slot->rwSessionCount); + } + } else { + PZ_Unlock(lock); + } + if (session) sftk_FreeSession(session); + } while (session != NULL); + } + return CKR_OK; } /* - * initialize one of the slot structures. figure out which by the ID + * shut down the databases. + * we get the slot lock (which also protects slot->certDB and slot->keyDB) + * and clear the values so the new users will not find the databases. + * once things are clear, we can release our references to the databases. + * The databases will close when the last reference is released. + * + * We use reference counts so that we don't crash if someone shuts down + * a token that another thread is actively using. */ -static CK_RV -sftk_DestroySlotData(SFTKSlot *slot) +static void +sftk_DBShutdown(SFTKSlot *slot) { - unsigned int i; - - if (slot->slotLock) { - PZ_DestroyLock(slot->slotLock); - slot->slotLock = NULL; - } - if (slot->sessionLock) { - for (i=0; i < slot->numSessionLocks; i++) { - if (slot->sessionLock[i]) { - PZ_DestroyLock(slot->sessionLock[i]); - slot->sessionLock[i] = NULL; - } - } + NSSLOWCERTCertDBHandle *certHandle; + NSSLOWKEYDBHandle *keyHandle; + PZ_Lock(slot->slotLock); + certHandle = slot->certDB; + slot->certDB = NULL; + keyHandle = slot->keyDB; + slot->keyDB = NULL; + PZ_Unlock(slot->slotLock); + if (certHandle) { + sftk_freeCertDB(certHandle); } - if (slot->objectLock) { - PZ_DestroyLock(slot->objectLock); - slot->objectLock = NULL; + if (keyHandle) { + sftk_freeKeyDB(keyHandle); } - if (slot->sessionLock) { - PORT_Free(slot->sessionLock); - slot->sessionLock = NULL; +} + +CK_RV +SFTK_ShutdownSlot(SFTKSlot *slot) +{ + /* make sure no new PK11 calls work except C_GetSlotInfo */ + slot->present = PR_FALSE; + + /* close all outstanding sessions + * the sessHashSize variable guarentees we have all the session + * mechanism set up */ + if (slot->head) { + sft_CloseAllSession(slot); + } + + /* clear all objects.. session objects are cleared as a result of + * closing all the sessions. We just need to clear the token object + * cache. slot->tokenHashTable guarentees we have the token + * infrastructure set up. */ + if (slot->tokenHashTable) { + SFTK_ClearTokenKeyHashTable(slot); } + /* clear the slot description for the next guy */ + PORT_Memset(slot->tokDescription, 0, sizeof(slot->tokDescription)); + + /* now shut down the databases. */ + sftk_DBShutdown(slot); + return CKR_OK; +} + +/* + * initialize one of the slot structures. figure out which by the ID + */ +CK_RV +SFTK_DestroySlotData(SFTKSlot *slot) +{ + unsigned int i; + + SFTK_ShutdownSlot(slot); + if (slot->tokenHashTable) { - PL_HashTableEnumerateEntries(slot->tokenHashTable, - sftk_freeHashItem,NULL); PL_HashTableDestroy(slot->tokenHashTable); slot->tokenHashTable = NULL; } if (slot->tokObjects) { - for(i=0; i < slot->tokObjHashSize; i++) { - SFTKObject *object = slot->tokObjects[i]; - slot->tokObjects[i] = NULL; - if (object) sftk_FreeObject(object); - } PORT_Free(slot->tokObjects); slot->tokObjects = NULL; } slot->tokObjHashSize = 0; + if (slot->head) { - for(i=0; i < slot->sessHashSize; i++) { - SFTKSession *session = slot->head[i]; - slot->head[i] = NULL; - if (session) sftk_FreeSession(session); - } PORT_Free(slot->head); slot->head = NULL; } slot->sessHashSize = 0; - sftk_DBShutdown(slot->certDB,slot->keyDB); + /* OK everything has been disassembled, now we can finally get rid + * of the locks */ + if (slot->slotLock) { + PZ_DestroyLock(slot->slotLock); + slot->slotLock = NULL; + } + if (slot->sessionLock) { + for (i=0; i < slot->numSessionLocks; i++) { + if (slot->sessionLock[i]) { + PZ_DestroyLock(slot->sessionLock[i]); + slot->sessionLock[i] = NULL; + } + } + PORT_Free(slot->sessionLock); + slot->sessionLock = NULL; + } + if (slot->objectLock) { + PZ_DestroyLock(slot->objectLock); + slot->objectLock = NULL; + } + if (slot->pwCheckLock) { + PR_DestroyLock(slot->pwCheckLock); + slot->pwCheckLock = NULL; + } PORT_Free(slot); return CKR_OK; } @@ -2718,7 +2915,7 @@ static void nscFreeAllSlots(int moduleIndex) PL_HashTableLookup(tmpSlotHashTable, (void *)slotID); PORT_Assert(slot); if (!slot) continue; - sftk_DestroySlotData(slot); + SFTK_DestroySlotData(slot); PL_HashTableRemove(tmpSlotHashTable, (void *)slotID); } PORT_Free(tmpSlotList); @@ -2738,9 +2935,7 @@ sftk_closePeer(PRBool isFIPS) if (slot == NULL) { return; } - sftk_DBShutdown(slot->certDB,slot->keyDB); - slot->certDB = NULL; - slot->keyDB = NULL; + sftk_DBShutdown(slot); return; } @@ -2764,6 +2959,8 @@ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS) crv = CKR_DEVICE_ERROR; /* better error code? checksum error? */ return crv; } + + loginWaitTime = PR_SecondsToInterval(1); } rv = secoid_Init(); @@ -2789,6 +2986,24 @@ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS) /* initialize the key and cert db's */ nsslowkey_SetDefaultKeyDBAlg (SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC); + if (init_args && (!(init_args->flags & CKF_OS_LOCKING_OK))) { + if (init_args->CreateMutex && init_args->DestroyMutex && + init_args->LockMutex && init_args->UnlockMutex) { + /* softoken always uses NSPR (ie. OS locking), and doesn't know how + * to use the lock functions provided by the application. + */ + crv = CKR_CANT_LOCK; + return crv; + } + if (init_args->CreateMutex || init_args->DestroyMutex || + init_args->LockMutex || init_args->UnlockMutex) { + /* only some of the lock functions were provided by the + * application. This is invalid per PKCS#11 spec. + */ + crv = CKR_ARGUMENTS_BAD; + return crv; + } + } crv = CKR_ARGUMENTS_BAD; if ((init_args && init_args->LibraryParameters)) { sftk_parameters paramStrings; @@ -2810,8 +3025,8 @@ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS) } for (i=0; i < paramStrings.token_count; i++) { - crv = - SFTK_SlotInit(paramStrings.configdir, ¶mStrings.tokens[i], + crv = SFTK_SlotInit(paramStrings.configdir, + ¶mStrings.tokens[i], moduleIndex); if (crv != CKR_OK) { nscFreeAllSlots(moduleIndex); @@ -2910,7 +3125,7 @@ CK_RV NSC_GetInfo(CK_INFO_PTR pInfo) c = __nss_softokn_rcsid[0] + __nss_softokn_sccsid[0]; pInfo->cryptokiVersion.major = 2; - pInfo->cryptokiVersion.minor = 11; + pInfo->cryptokiVersion.minor = 20; PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32); pInfo->libraryVersion.major = NSS_VMAJOR; pInfo->libraryVersion.minor = NSS_VMINOR; @@ -2943,7 +3158,7 @@ CK_RV NSC_GetSlotList(CK_BBOOL tokenPresent, /* NSC_GetSlotInfo obtains information about a particular slot in the system. */ CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { - SFTKSlot *slot = sftk_SlotFromID(slotID); + SFTKSlot *slot = sftk_SlotFromID(slotID, PR_TRUE); if (slot == NULL) return CKR_SLOT_ID_INVALID; pInfo->firmwareVersion.major = 0; @@ -2951,7 +3166,11 @@ CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32); PORT_Memcpy(pInfo->slotDescription,slot->slotDescription,64); - pInfo->flags = CKF_TOKEN_PRESENT; + pInfo->flags = (slot->present) ? CKF_TOKEN_PRESENT : 0; + /* all user defined slots are defined as removable */ + if (slotID >= SFTK_MIN_USER_SLOT_ID) { + pInfo->flags |= CKF_REMOVABLE_DEVICE; + } /* ok we really should read it out of the keydb file. */ /* pInfo->hardwareVersion.major = NSSLOWKEY_DB_FILE_VERSION; */ pInfo->hardwareVersion.major = NSS_VMAJOR; @@ -2965,11 +3184,12 @@ CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) * been changed underneath us. */ static PRBool -sftk_checkNeedLogin(SFTKSlot *slot) +sftk_checkNeedLogin(SFTKSlot *slot, NSSLOWKEYDBHandle *keyHandle) { if (slot->password) { - if (nsslowkey_CheckKeyDBPassword(slot->keyDB,slot->password) - == SECSuccess) { + SECStatus rv; + rv = nsslowkey_CheckKeyDBPassword(keyHandle,slot->password); + if ( rv == SECSuccess) { return slot->needLogin; } else { SECITEM_FreeItem(slot->password, PR_TRUE); @@ -2978,7 +3198,7 @@ sftk_checkNeedLogin(SFTKSlot *slot) } } slot->needLogin = - (PRBool)!sftk_hasNullPassword(slot->keyDB,&slot->password); + (PRBool)!sftk_hasNullPassword(keyHandle,&slot->password); return (slot->needLogin); } @@ -2986,7 +3206,7 @@ sftk_checkNeedLogin(SFTKSlot *slot) * the system. */ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) { - SFTKSlot *slot = sftk_SlotFromID(slotID); + SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE); NSSLOWKEYDBHandle *handle; if (slot == NULL) return CKR_SLOT_ID_INVALID; @@ -3001,7 +3221,7 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) pInfo->firmwareVersion.major = 0; pInfo->firmwareVersion.minor = 0; PORT_Memcpy(pInfo->label,slot->tokDescription,32); - handle = slot->keyDB; + handle = sftk_getKeyDB(slot); if (handle == NULL) { pInfo->flags= CKF_RNG | CKF_WRITE_PROTECTED | CKF_THREAD_SAFE; pInfo->ulMaxPinLen = 0; @@ -3024,23 +3244,21 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) */ if (nsslowkey_HasKeyDBPassword(handle) == SECFailure) { pInfo->flags = CKF_THREAD_SAFE | CKF_LOGIN_REQUIRED; - } else if (!sftk_checkNeedLogin(slot)) { + } else if (!sftk_checkNeedLogin(slot,handle)) { pInfo->flags = CKF_THREAD_SAFE | CKF_USER_PIN_INITIALIZED; } else { pInfo->flags = CKF_THREAD_SAFE | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED; } pInfo->ulMaxPinLen = SFTK_MAX_PIN; - pInfo->ulMinPinLen = 0; - if (slot->minimumPinLen > 0) { - pInfo->ulMinPinLen = (CK_ULONG)slot->minimumPinLen; - } + pInfo->ulMinPinLen = (CK_ULONG)slot->minimumPinLen; pInfo->ulTotalPublicMemory = 1; pInfo->ulFreePublicMemory = 1; pInfo->ulTotalPrivateMemory = 1; pInfo->ulFreePrivateMemory = 1; pInfo->hardwareVersion.major = CERT_DB_FILE_VERSION; pInfo->hardwareVersion.minor = handle->version; + sftk_freeKeyDB(handle); } return CKR_OK; } @@ -3155,7 +3373,7 @@ sftk_TurnOffUser(NSSLOWCERTCertificate *cert, SECItem *k, void *arg) /* NSC_InitToken initializes a token. */ CK_RV NSC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin, CK_ULONG ulPinLen,CK_CHAR_PTR pLabel) { - SFTKSlot *slot = sftk_SlotFromID(slotID); + SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE); NSSLOWKEYDBHandle *handle; NSSLOWCERTCertDBHandle *certHandle; SECStatus rv; @@ -3194,19 +3412,23 @@ CK_RV NSC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin, PZ_Unlock(slot->objectLock); /* then clear out the key database */ - handle = slot->keyDB; + handle = sftk_getKeyDB(slot); if (handle == NULL) { return CKR_TOKEN_WRITE_PROTECTED; } - /* what to do on an error here? */ rv = nsslowkey_ResetKeyDB(handle); + sftk_freeKeyDB(handle); + if (rv != SECSuccess) { + return CKR_DEVICE_ERROR; + } /* finally mark all the user certs as non-user certs */ - certHandle = slot->certDB; + certHandle = sftk_getCertDB(slot); if (certHandle == NULL) return CKR_OK; nsslowcert_TraversePermCerts(certHandle,sftk_TurnOffUser, NULL); + sftk_freeCertDB(certHandle); return CKR_OK; /*is this the right function for not implemented*/ } @@ -3216,49 +3438,53 @@ CK_RV NSC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin, CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pPin, CK_ULONG ulPinLen) { - SFTKSession *sp; + SFTKSession *sp = NULL; SFTKSlot *slot; - NSSLOWKEYDBHandle *handle; + NSSLOWKEYDBHandle *handle = NULL; SECItem *newPin; char newPinStr[SFTK_MAX_PIN+1]; SECStatus rv; + CK_RV crv = CKR_SESSION_HANDLE_INVALID; sp = sftk_SessionFromHandle(hSession); if (sp == NULL) { - return CKR_SESSION_HANDLE_INVALID; + goto loser; } slot = sftk_SlotFromSession(sp); if (slot == NULL) { - sftk_FreeSession(sp); - return CKR_SESSION_HANDLE_INVALID;; + goto loser; } - handle = slot->keyDB; + handle = sftk_getKeyDB(slot); if (handle == NULL) { - sftk_FreeSession(sp); - return CKR_PIN_LEN_RANGE; + crv = CKR_PIN_LEN_RANGE; + goto loser; } if (sp->info.state != CKS_RW_SO_FUNCTIONS) { - sftk_FreeSession(sp); - return CKR_USER_NOT_LOGGED_IN; + crv = CKR_USER_NOT_LOGGED_IN; + goto loser; } sftk_FreeSession(sp); + sp = NULL; /* make sure the pins aren't too long */ if (ulPinLen > SFTK_MAX_PIN) { - return CKR_PIN_LEN_RANGE; + crv = CKR_PIN_LEN_RANGE; + goto loser; } if (ulPinLen < (CK_ULONG)slot->minimumPinLen) { - return CKR_PIN_LEN_RANGE; + crv = CKR_PIN_LEN_RANGE; + goto loser; } if (nsslowkey_HasKeyDBPassword(handle) != SECFailure) { - return CKR_DEVICE_ERROR; + crv = CKR_DEVICE_ERROR; + goto loser; } /* convert to null terminated string */ @@ -3271,6 +3497,8 @@ CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession, /* change the data base */ rv = nsslowkey_SetKeyDBPassword(handle,newPin); + sftk_freeKeyDB(handle); + handle = NULL; /* Now update our local copy of the pin */ if (rv == SECSuccess) { @@ -3282,7 +3510,16 @@ CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession, return CKR_OK; } SECITEM_ZfreeItem(newPin, PR_TRUE); - return CKR_PIN_INCORRECT; + crv = CKR_PIN_INCORRECT; + +loser: + if (sp) { + sftk_FreeSession(sp); + } + if (handle) { + sftk_freeKeyDB(handle); + } + return crv; } @@ -3291,45 +3528,48 @@ CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession, CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen) { - SFTKSession *sp; + SFTKSession *sp = NULL; SFTKSlot *slot; - NSSLOWKEYDBHandle *handle; + NSSLOWKEYDBHandle *handle = NULL; SECItem *newPin; SECItem *oldPin; char newPinStr[SFTK_MAX_PIN+1],oldPinStr[SFTK_MAX_PIN+1]; SECStatus rv; + CK_RV crv = CKR_SESSION_HANDLE_INVALID; sp = sftk_SessionFromHandle(hSession); if (sp == NULL) { - return CKR_SESSION_HANDLE_INVALID; + goto loser; } slot = sftk_SlotFromSession(sp); if (!slot) { - sftk_FreeSession(sp); - return CKR_SESSION_HANDLE_INVALID;; + goto loser; } - handle = slot->keyDB; + handle = sftk_getKeyDB(slot); if (handle == NULL) { sftk_FreeSession(sp); return CKR_PIN_LEN_RANGE; } if (slot->needLogin && sp->info.state != CKS_RW_USER_FUNCTIONS) { - sftk_FreeSession(sp); - return CKR_USER_NOT_LOGGED_IN; + crv = CKR_USER_NOT_LOGGED_IN; + goto loser; } sftk_FreeSession(sp); + sp = NULL; /* make sure the pins aren't too long */ if ((ulNewLen > SFTK_MAX_PIN) || (ulOldLen > SFTK_MAX_PIN)) { - return CKR_PIN_LEN_RANGE; + crv = CKR_PIN_LEN_RANGE; + goto loser; } if (ulNewLen < (CK_ULONG)slot->minimumPinLen) { - return CKR_PIN_LEN_RANGE; + crv = CKR_PIN_LEN_RANGE; + goto loser; } @@ -3345,8 +3585,15 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, PORT_Memset(newPinStr,0,sizeof(newPinStr)); PORT_Memset(oldPinStr,0,sizeof(oldPinStr)); - /* change the data base */ + /* change the data base password */ + PR_Lock(slot->pwCheckLock); rv = nsslowkey_ChangeKeyDBPassword(handle,oldPin,newPin); + sftk_freeKeyDB(handle); + handle = NULL; + if ((rv != SECSuccess) && (slot->slotID == FIPS_SLOT_ID)) { + PR_Sleep(loginWaitTime); + } + PR_Unlock(slot->pwCheckLock); /* Now update our local copy of the pin */ SECITEM_ZfreeItem(oldPin, PR_TRUE); @@ -3359,7 +3606,15 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, return CKR_OK; } SECITEM_ZfreeItem(newPin, PR_TRUE); - return CKR_PIN_INCORRECT; + crv = CKR_PIN_INCORRECT; +loser: + if (sp) { + sftk_FreeSession(sp); + } + if (handle) { + sftk_freeKeyDB(handle); + } + return crv; } /* NSC_OpenSession opens a session between an application and a token. */ @@ -3371,7 +3626,7 @@ CK_RV NSC_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, SFTKSession *session; SFTKSession *sameID; - slot = sftk_SlotFromID(slotID); + slot = sftk_SlotFromID(slotID, PR_FALSE); if (slot == NULL) return CKR_SLOT_ID_INVALID; /* new session (we only have serial sessions) */ @@ -3462,56 +3717,15 @@ CK_RV NSC_CloseSession(CK_SESSION_HANDLE hSession) CK_RV NSC_CloseAllSessions (CK_SLOT_ID slotID) { SFTKSlot *slot; - SECItem *pw = NULL; - SFTKSession *session; - unsigned int i; - slot = sftk_SlotFromID(slotID); + slot = sftk_SlotFromID(slotID, PR_FALSE); if (slot == NULL) return CKR_SLOT_ID_INVALID; - /* first log out the card */ - PZ_Lock(slot->slotLock); - pw = slot->password; - slot->isLoggedIn = PR_FALSE; - slot->password = NULL; - PZ_Unlock(slot->slotLock); - if (pw) SECITEM_ZfreeItem(pw, PR_TRUE); - - /* now close all the current sessions */ - /* NOTE: If you try to open new sessions before NSC_CloseAllSessions - * completes, some of those new sessions may or may not be closed by - * NSC_CloseAllSessions... but any session running when this code starts - * will guarrenteed be close, and no session will be partially closed */ - for (i=0; i < slot->sessHashSize; i++) { - PZLock *lock = SFTK_SESSION_LOCK(slot,i); - do { - PZ_Lock(lock); - session = slot->head[i]; - /* hand deque */ - /* this duplicates function of NSC_close session functions, but - * because we know that we are freeing all the sessions, we can - * do more efficient processing */ - if (session) { - slot->head[i] = session->next; - if (session->next) session->next->prev = NULL; - session->next = session->prev = NULL; - PZ_Unlock(lock); - PZ_Lock(slot->slotLock); - --slot->sessionCount; - PZ_Unlock(slot->slotLock); - if (session->info.flags & CKF_RW_SESSION) { - PR_AtomicDecrement(&slot->rwSessionCount); - } - } else { - PZ_Unlock(lock); - } - if (session) sftk_FreeSession(session); - } while (session != NULL); - } - return CKR_OK; + return sft_CloseAllSession(slot); } + /* NSC_GetSessionInfo obtains information about the session. */ CK_RV NSC_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo) @@ -3534,6 +3748,8 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, SFTKSession *session; NSSLOWKEYDBHandle *handle; CK_FLAGS sessionFlags; + SECStatus rv; + CK_RV crv; SECItem *pin; char pinStr[SFTK_MAX_PIN+1]; @@ -3543,14 +3759,17 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, /* make sure the session is valid */ session = sftk_SessionFromHandle(hSession); - if (session == NULL) return CKR_SESSION_HANDLE_INVALID; + if (session == NULL) { + return CKR_SESSION_HANDLE_INVALID; + } sessionFlags = session->info.flags; sftk_FreeSession(session); session = NULL; /* can't log into the Netscape Slot */ - if (slot->slotID == NETSCAPE_SLOT_ID) + if (slot->slotID == NETSCAPE_SLOT_ID) { return CKR_USER_TYPE_INVALID; + } if (slot->isLoggedIn) return CKR_USER_ALREADY_LOGGED_IN; slot->ssoLoggedIn = PR_FALSE; @@ -3561,7 +3780,7 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, PORT_Memcpy(pinStr,pPin,ulPinLen); pinStr[ulPinLen] = 0; - handle = slot->keyDB; + handle = sftk_getKeyDB(slot); if (handle == NULL) { return CKR_USER_TYPE_INVALID; } @@ -3571,7 +3790,8 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, * password if and only if we haven't initialized the KEY DB yet. * We only allow this on a RW session. */ - if (nsslowkey_HasKeyDBPassword(handle) == SECFailure) { + rv = nsslowkey_HasKeyDBPassword(handle); + if (rv == SECFailure) { /* allow SSO's to log in only if there is not password on the * key database */ if (((userType == CKU_SO) && (sessionFlags & CKF_RW_SESSION)) @@ -3588,22 +3808,39 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, PZ_Unlock(slot->slotLock); sftk_update_all_states(slot); SECITEM_ZfreeItem(pw,PR_TRUE); - return CKR_OK; + crv = CKR_OK; + goto done; } - return CKR_PIN_INCORRECT; + crv = CKR_PIN_INCORRECT; + goto done; } - return CKR_USER_TYPE_INVALID; + crv = CKR_USER_TYPE_INVALID; + goto done; } /* don't allow the SSO to log in if the user is already initialized */ - if (userType != CKU_USER) { return CKR_USER_TYPE_INVALID; } + if (userType != CKU_USER) { + crv = CKR_USER_TYPE_INVALID; + goto done; + } /* build the hashed pins which we pass around */ pin = nsslowkey_HashPassword(pinStr,handle->global_salt); - if (pin == NULL) return CKR_HOST_MEMORY; + if (pin == NULL) { + crv = CKR_HOST_MEMORY; + goto done; + } - if (nsslowkey_CheckKeyDBPassword(handle,pin) == SECSuccess) { + PR_Lock(slot->pwCheckLock); + rv = nsslowkey_CheckKeyDBPassword(handle,pin); + sftk_freeKeyDB(handle); + handle = NULL; + if ((rv != SECSuccess) && (slot->slotID == FIPS_SLOT_ID)) { + PR_Sleep(loginWaitTime); + } + PR_Unlock(slot->pwCheckLock); + if (rv == SECSuccess) { SECItem *tmp; PZ_Lock(slot->slotLock); tmp = slot->password; @@ -3618,7 +3855,12 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, } SECITEM_ZfreeItem(pin, PR_TRUE); - return CKR_PIN_INCORRECT; + crv = CKR_PIN_INCORRECT; +done: + if (handle) { + sftk_freeKeyDB(handle); + } + return crv; } /* NSC_Logout logs a user out from a token. */ @@ -3647,6 +3889,98 @@ CK_RV NSC_Logout(CK_SESSION_HANDLE hSession) return CKR_OK; } +/* + * Create a new slot on the fly. The slot that is passed in is the + * slot the request came from. Only the crypto or FIPS slots can + * be used. The resulting slot will live in the same module as + * the slot the request was passed to. object is the creation object + * that specifies the module spec for the new slot. + */ +static CK_RV sftk_CreateNewSlot(SFTKSlot *slot, CK_OBJECT_CLASS class, + SFTKObject *object) +{ + CK_SLOT_ID idMin, idMax; + PRBool isFIPS = PR_FALSE; + unsigned long moduleIndex; + SFTKAttribute *attribute; + sftk_parameters paramStrings; + char *paramString; + CK_SLOT_ID slotID = 0; + SFTKSlot *newSlot = NULL; + CK_RV crv = CKR_OK; + + /* only the crypto or FIPS slots can create new slot objects */ + if (slot->slotID == NETSCAPE_SLOT_ID) { + idMin = SFTK_MIN_USER_SLOT_ID; + idMax = SFTK_MAX_USER_SLOT_ID; + moduleIndex = NSC_NON_FIPS_MODULE; + isFIPS = PR_FALSE; + } else if (slot->slotID == FIPS_SLOT_ID) { + idMin = SFTK_MIN_FIPS_USER_SLOT_ID; + idMax = SFTK_MAX_FIPS_USER_SLOT_ID; + moduleIndex = NSC_FIPS_MODULE; + isFIPS = PR_TRUE; + } else { + return CKR_ATTRIBUTE_VALUE_INVALID; + } + attribute = sftk_FindAttribute(object,CKA_NETSCAPE_MODULE_SPEC); + if (attribute == NULL) { + return CKR_TEMPLATE_INCOMPLETE; + } + paramString = (unsigned char *)attribute->attrib.pValue; + crv = secmod_parseParameters(paramString, ¶mStrings, isFIPS); + if (crv != CKR_OK) { + goto loser; + } + + /* enforce only one at a time */ + if (paramStrings.token_count != 1) { + crv = CKR_ATTRIBUTE_VALUE_INVALID; + goto loser; + } + + slotID = paramStrings.tokens[0].slotID; + + /* stay within the valid ID space */ + if ((slotID < idMin) || (slotID > idMax)) { + crv = CKR_ATTRIBUTE_VALUE_INVALID; + goto loser; + } + + /* unload any existing slot at this id */ + newSlot = sftk_SlotFromID(slotID, PR_TRUE); + if (newSlot && newSlot->present) { + crv = SFTK_ShutdownSlot(newSlot); + if (crv != CKR_OK) { + goto loser; + } + } + + /* if we were just planning on deleting the slot, then do so now */ + if (class == CKO_NETSCAPE_DELSLOT) { + /* sort of a unconventional use of this error code, be we are + * overusing CKR_ATTRIBUTE_VALUE_INVALID, and it does apply */ + crv = newSlot ? CKR_OK : CKR_SLOT_ID_INVALID; + goto loser; /* really exit */ + } + + if (newSlot) { + crv = SFTK_SlotReInit(newSlot, paramStrings.configdir, + ¶mStrings.tokens[0], moduleIndex); + } else { + crv = SFTK_SlotInit(paramStrings.configdir, + ¶mStrings.tokens[0], moduleIndex); + } + if (crv != CKR_OK) { + goto loser; + } +loser: + secmod_freeParams(¶mStrings); + sftk_FreeAttribute(attribute); + + return crv; +} + /* NSC_CreateObject creates a new object. */ CK_RV NSC_CreateObject(CK_SESSION_HANDLE hSession, @@ -3656,9 +3990,11 @@ CK_RV NSC_CreateObject(CK_SESSION_HANDLE hSession, SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession); SFTKSession *session; SFTKObject *object; + CK_OBJECT_CLASS class; CK_RV crv; int i; + *phObject = CK_INVALID_HANDLE; /* * now lets create an object to hang the attributes off of @@ -3677,6 +4013,9 @@ CK_RV NSC_CreateObject(CK_SESSION_HANDLE hSession, sftk_FreeObject(object); return crv; } + if ((pTemplate[i].type == CKA_CLASS) && pTemplate[i].pValue) { + class = *(CK_OBJECT_CLASS *)pTemplate[i].pValue; + } } /* get the session */ @@ -3687,10 +4026,19 @@ CK_RV NSC_CreateObject(CK_SESSION_HANDLE hSession, } /* + * handle pseudo objects (CKO_NEWSLOT) + */ + if ((class == CKO_NETSCAPE_NEWSLOT) || (class == CKO_NETSCAPE_DELSLOT)) { + crv = sftk_CreateNewSlot(slot, class, object); + goto done; + } + + /* * handle the base object stuff */ crv = sftk_handleObject(object,session); *phObject = object->handle; +done: sftk_FreeSession(session); sftk_FreeObject(object); @@ -3698,6 +4046,7 @@ CK_RV NSC_CreateObject(CK_SESSION_HANDLE hSession, } + /* NSC_CopyObject copies an object, creating a new object for the copy. */ CK_RV NSC_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, @@ -3983,7 +4332,7 @@ sftk_searchCrls(SFTKSlot *slot, SECItem *derSubject, PRBool isKrl, { NSSLOWCERTCertDBHandle *certHandle = NULL; - certHandle = slot->certDB; + certHandle = sftk_getCertDB(slot); if (certHandle == NULL) { return; } @@ -4009,6 +4358,7 @@ sftk_searchCrls(SFTKSlot *slot, SECItem *derSubject, PRBool isKrl, nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeKeyRevocation, sftk_crl_collect, (void *)&crlData); } + sftk_freeCertDB(certHandle); } /* @@ -4016,6 +4366,7 @@ sftk_searchCrls(SFTKSlot *slot, SECItem *derSubject, PRBool isKrl, */ typedef struct sftkKeyDataStr { SFTKSlot *slot; + NSSLOWKEYDBHandle *keyHandle; SFTKSearchResults *searchHandles; SECItem *id; CK_ATTRIBUTE *template; @@ -4041,7 +4392,7 @@ sftk_key_collect(DBT *key, DBT *data, void *arg) tmpDBKey.len = key->size; tmpDBKey.type = siBuffer; - PORT_Assert(slot->keyDB); + PORT_Assert(keyData->keyHandle); if (!keyData->strict && keyData->id) { SECItem result; PRBool haveMatch= PR_FALSE; @@ -4051,7 +4402,7 @@ sftk_key_collect(DBT *key, DBT *data, void *arg) if (keyData->id->len == 0) { /* Make sure this isn't a NSC_KEY */ - privKey = nsslowkey_FindKeyByPublicKey(keyData->slot->keyDB, + privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle, &tmpDBKey, keyData->slot->password); if (privKey) { haveMatch = isSecretKey(privKey) ? @@ -4094,7 +4445,7 @@ sftk_key_collect(DBT *key, DBT *data, void *arg) return SECSuccess; } - privKey = nsslowkey_FindKeyByPublicKey(keyData->slot->keyDB, &tmpDBKey, + privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle, &tmpDBKey, keyData->slot->password); if ( privKey == NULL ) { goto loser; @@ -4139,7 +4490,7 @@ sftk_searchKeys(SFTKSlot *slot, SECItem *key_id, PRBool isLoggedIn, sftkKeyData keyData; PRBool found = PR_FALSE; - keyHandle = slot->keyDB; + keyHandle = sftk_getKeyDB(slot); if (keyHandle == NULL) { return; } @@ -4166,19 +4517,20 @@ sftk_searchKeys(SFTKSlot *slot, SECItem *key_id, PRBool isLoggedIn, } /* don't do the traversal if we have an up to date db */ if (keyHandle->version != 3) { - return; + goto loser; } /* don't do the traversal if it can't possibly be the correct id */ /* all soft token id's are SHA1_HASH_LEN's */ if (key_id->len != SHA1_LENGTH) { - return; + goto loser; } if (found) { /* if we already found some keys, don't do the traversal */ - return; + goto loser; } } keyData.slot = slot; + keyData.keyHandle = keyHandle; keyData.searchHandles = search; keyData.id = key_id; keyData.template = pTemplate; @@ -4188,6 +4540,9 @@ sftk_searchKeys(SFTKSlot *slot, SECItem *key_id, PRBool isLoggedIn, keyData.strict = mustStrict ? mustStrict : NSC_STRICT; nsslowkey_TraverseKeys(keyHandle, sftk_key_collect, &keyData); +loser: + sftk_freeKeyDB(keyHandle); + } /* @@ -4301,7 +4656,7 @@ sftk_searchCertsAndTrust(SFTKSlot *slot, SECItem *derCert, SECItem *name, sftkCertData certData; int i; - certHandle = slot->certDB; + certHandle = sftk_getCertDB(slot); if (certHandle == NULL) return; certData.slot = slot; @@ -4387,10 +4742,11 @@ sftk_searchCertsAndTrust(SFTKSlot *slot, SECItem *derCert, SECItem *name, } else { /* we aren't filtering the certs, we are working on all, so turn * on the strict filters. */ - certData.strict = PR_TRUE; + certData.strict = PR_TRUE; sftk_CertSetupData(&certData,NSC_CERT_BLOCK_SIZE); nsslowcert_TraversePermCerts(certHandle, sftk_cert_collect2, &certData); } + sftk_freeCertDB(certHandle); /* * build the handles @@ -4421,13 +4777,14 @@ sftk_searchSMime(SFTKSlot *slot, SECItem *email, SFTKSearchResults *handles, NSSLOWCERTCertDBHandle *certHandle = NULL; certDBEntrySMime *entry; - certHandle = slot->certDB; + certHandle = sftk_getCertDB(slot); if (certHandle == NULL) return; if (email->data != NULL) { char *tmp_name = (char*)PORT_Alloc(email->len+1); if (tmp_name == NULL) { + sftk_freeCertDB(certHandle); return; } PORT_Memcpy(tmp_name,email->data,email->len); @@ -4446,6 +4803,7 @@ sftk_searchSMime(SFTKSlot *slot, SECItem *email, SFTKSearchResults *handles, } PORT_Free(tmp_name); } + sftk_freeCertDB(certHandle); return; } diff --git a/security/nss/lib/softoken/pkcs11c.c b/security/nss/lib/softoken/pkcs11c.c index 97315fcbb..56eb1814c 100644 --- a/security/nss/lib/softoken/pkcs11c.c +++ b/security/nss/lib/softoken/pkcs11c.c @@ -122,12 +122,6 @@ sftk_FreePrivKey(NSSLOWKEYPrivateKey *key, PRBool freeit) } static void -sftk_HMAC_Destroy(HMACContext *context, PRBool freeit) -{ - HMAC_Destroy(context); -} - -static void sftk_Space(void *data, PRBool freeit) { PORT_Free(data); @@ -1266,7 +1260,7 @@ sftk_doHMACInit(SFTKSessionContext *context,HASH_HashType hash, SFTKAttribute *keyval; HMACContext *HMACcontext; CK_ULONG *intpointer; - const SECHashObject *hashObj = &SECRawHashObjects[hash]; + const SECHashObject *hashObj = HASH_GetRawHashObject(hash); PRBool isFIPS = (key->slot->slotID == FIPS_SLOT_ID); /* required by FIPS 198 Section 4 */ @@ -1292,7 +1286,7 @@ sftk_doHMACInit(SFTKSessionContext *context,HASH_HashType hash, context->hashUpdate = (SFTKHash) HMAC_Update; context->end = (SFTKEnd) HMAC_Finish; - context->hashdestroy = (SFTKDestroy) sftk_HMAC_Destroy; + context->hashdestroy = (SFTKDestroy) HMAC_Destroy; intpointer = (CK_ULONG *) PORT_Alloc(sizeof(CK_ULONG)); if (intpointer == NULL) { return CKR_HOST_MEMORY; @@ -1608,17 +1602,16 @@ nsc_DSA_Sign_Stub(void *ctx, void *sigBuf, unsigned int *sigLen, unsigned int maxSigLen, void *dataBuf, unsigned int dataLen) { - SECItem signature = { 0 }, digest; + SECItem signature, digest; SECStatus rv; NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx; - (void)SECITEM_AllocItem(NULL, &signature, maxSigLen); + signature.data = (unsigned char *)sigBuf; + signature.len = maxSigLen; digest.data = (unsigned char *)dataBuf; digest.len = dataLen; rv = DSA_SignDigest(&(key->u.dsa), &signature, &digest); *sigLen = signature.len; - PORT_Memcpy(sigBuf, signature.data, signature.len); - SECITEM_FreeItem(&signature, PR_FALSE); return rv; } @@ -1642,17 +1635,16 @@ nsc_ECDSASignStub(void *ctx, void *sigBuf, unsigned int *sigLen, unsigned int maxSigLen, void *dataBuf, unsigned int dataLen) { - SECItem signature = { 0 }, digest; + SECItem signature, digest; SECStatus rv; NSSLOWKEYPrivateKey *key = (NSSLOWKEYPrivateKey *)ctx; - (void)SECITEM_AllocItem(NULL, &signature, maxSigLen); + signature.data = (unsigned char *)sigBuf; + signature.len = maxSigLen; digest.data = (unsigned char *)dataBuf; digest.len = dataLen; rv = ECDSA_SignDigest(&(key->u.ec), &signature, &digest); *sigLen = signature.len; - PORT_Memcpy(sigBuf, signature.data, signature.len); - SECITEM_FreeItem(&signature, PR_FALSE); return rv; } #endif /* NSS_ENABLE_ECC */ @@ -2502,6 +2494,7 @@ nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key) CK_ULONG counter; unsigned int seedBits = 0; unsigned int primeBits; + unsigned int j; CK_RV crv = CKR_OK; PQGParams *params = NULL; PQGVerify *vfy = NULL; @@ -2513,6 +2506,10 @@ nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key) } primeBits = (unsigned int) *(CK_ULONG *)attribute->attrib.pValue; sftk_FreeAttribute(attribute); + j = PQG_PBITS_TO_INDEX(primeBits); + if (j == (unsigned int)-1) { + return CKR_ATTRIBUTE_VALUE_INVALID; + } attribute = sftk_FindAttribute(key, CKA_NETSCAPE_PQG_SEED_BITS); if (attribute != NULL) { @@ -2524,9 +2521,9 @@ nsc_parameter_gen(CK_KEY_TYPE key_type, SFTKObject *key) sftk_DeleteAttributeType(key,CKA_NETSCAPE_PQG_SEED_BITS); if (seedBits == 0) { - rv = PQG_ParamGen(primeBits, ¶ms, &vfy); + rv = PQG_ParamGen(j, ¶ms, &vfy); } else { - rv = PQG_ParamGenSeedLen(primeBits,seedBits/8, ¶ms, &vfy); + rv = PQG_ParamGenSeedLen(j,seedBits/8, ¶ms, &vfy); } if (rv != SECSuccess) { @@ -2931,6 +2928,287 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, return crv; } +#define PAIRWISE_DIGEST_LENGTH SHA1_LENGTH /* 160-bits */ +#define PAIRWISE_MESSAGE_LENGTH 20 /* 160-bits */ + +/* + * FIPS 140-2 pairwise consistency check utilized to validate key pair. + * + * This function returns + * CKR_OK if pairwise consistency check passed + * CKR_GENERAL_ERROR if pairwise consistency check failed + * other error codes if paiswise consistency check could not be + * performed, for example, CKR_HOST_MEMORY. + */ +static CK_RV +sftk_PairwiseConsistencyCheck(CK_SESSION_HANDLE hSession, + SFTKObject *publicKey, SFTKObject *privateKey, CK_KEY_TYPE keyType) +{ + /* + * Key type Mechanism type + * -------------------------------- + * For encrypt/decrypt: CKK_RSA => CKM_RSA_PKCS + * others => CKM_INVALID_MECHANISM + * + * For sign/verify: CKK_RSA => CKM_RSA_PKCS + * CKK_DSA => CKM_DSA + * CKK_EC => CKM_ECDSA + * others => CKM_INVALID_MECHANISM + * + * None of these mechanisms has a parameter. + */ + CK_MECHANISM mech = {0, NULL, 0}; + + CK_ULONG modulusLen; + PRBool isEncryptable = PR_FALSE; + PRBool canSignVerify = PR_FALSE; + PRBool isDerivable = PR_FALSE; + CK_RV crv; + + /* Variables used for Encrypt/Decrypt functions. */ + unsigned char *known_message = (unsigned char *)"Known Crypto Message"; + unsigned char plaintext[PAIRWISE_MESSAGE_LENGTH]; + CK_ULONG bytes_decrypted; + unsigned char *ciphertext; + unsigned char *text_compared; + CK_ULONG bytes_encrypted; + CK_ULONG bytes_compared; + + /* Variables used for Signature/Verification functions. */ + /* always uses SHA-1 digest */ + unsigned char *known_digest = (unsigned char *)"Mozilla Rules World!"; + unsigned char *signature; + CK_ULONG signature_length; + + if (keyType == CKK_RSA) { + SFTKAttribute *attribute; + + /* Get modulus length of private key. */ + attribute = sftk_FindAttribute(privateKey, CKA_MODULUS); + if (attribute == NULL) { + return CKR_DEVICE_ERROR; + } + modulusLen = attribute->attrib.ulValueLen; + if (*(unsigned char *)attribute->attrib.pValue == 0) { + modulusLen--; + } + sftk_FreeAttribute(attribute); + } + + /**************************************************/ + /* Pairwise Consistency Check of Encrypt/Decrypt. */ + /**************************************************/ + + isEncryptable = sftk_isTrue(privateKey, CKA_DECRYPT); + + /* + * If the decryption attribute is set, attempt to encrypt + * with the public key and decrypt with the private key. + */ + if (isEncryptable) { + if (keyType != CKK_RSA) { + return CKR_DEVICE_ERROR; + } + bytes_encrypted = modulusLen; + mech.mechanism = CKM_RSA_PKCS; + + /* Allocate space for ciphertext. */ + ciphertext = (unsigned char *) PORT_ZAlloc(bytes_encrypted); + if (ciphertext == NULL) { + return CKR_HOST_MEMORY; + } + + /* Prepare for encryption using the public key. */ + crv = NSC_EncryptInit(hSession, &mech, publicKey->handle); + if (crv != CKR_OK) { + PORT_Free(ciphertext); + return crv; + } + + /* Encrypt using the public key. */ + crv = NSC_Encrypt(hSession, + known_message, + PAIRWISE_MESSAGE_LENGTH, + ciphertext, + &bytes_encrypted); + if (crv != CKR_OK) { + PORT_Free(ciphertext); + return crv; + } + + /* Always use the smaller of these two values . . . */ + bytes_compared = PR_MIN(bytes_encrypted, PAIRWISE_MESSAGE_LENGTH); + + /* + * If there was a failure, the plaintext + * goes at the end, therefore . . . + */ + text_compared = ciphertext + bytes_encrypted - bytes_compared; + + /* + * Check to ensure that ciphertext does + * NOT EQUAL known input message text + * per FIPS PUB 140-2 directive. + */ + if (PORT_Memcmp(text_compared, known_message, + bytes_compared) == 0) { + /* Set error to Invalid PRIVATE Key. */ + PORT_SetError(SEC_ERROR_INVALID_KEY); + PORT_Free(ciphertext); + return CKR_GENERAL_ERROR; + } + + /* Prepare for decryption using the private key. */ + crv = NSC_DecryptInit(hSession, &mech, privateKey->handle); + if (crv != CKR_OK) { + PORT_Free(ciphertext); + return crv; + } + + memset(plaintext, 0, PAIRWISE_MESSAGE_LENGTH); + + /* + * Initialize bytes decrypted to be the + * expected PAIRWISE_MESSAGE_LENGTH. + */ + bytes_decrypted = PAIRWISE_MESSAGE_LENGTH; + + /* + * Decrypt using the private key. + * NOTE: No need to reset the + * value of bytes_encrypted. + */ + crv = NSC_Decrypt(hSession, + ciphertext, + bytes_encrypted, + plaintext, + &bytes_decrypted); + + /* Finished with ciphertext; free it. */ + PORT_Free(ciphertext); + + if (crv != CKR_OK) { + return crv; + } + + /* + * Check to ensure that the output plaintext + * does EQUAL known input message text. + */ + if ((bytes_decrypted != PAIRWISE_MESSAGE_LENGTH) || + (PORT_Memcmp(plaintext, known_message, + PAIRWISE_MESSAGE_LENGTH) != 0)) { + /* Set error to Bad PUBLIC Key. */ + PORT_SetError(SEC_ERROR_BAD_KEY); + return CKR_GENERAL_ERROR; + } + } + + /**********************************************/ + /* Pairwise Consistency Check of Sign/Verify. */ + /**********************************************/ + + canSignVerify = sftk_isTrue(privateKey, CKA_SIGN); + + if (canSignVerify) { + /* Determine length of signature. */ + switch (keyType) { + case CKK_RSA: + signature_length = modulusLen; + mech.mechanism = CKM_RSA_PKCS; + break; + case CKK_DSA: + signature_length = DSA_SIGNATURE_LEN; + mech.mechanism = CKM_DSA; + break; +#ifdef NSS_ENABLE_ECC + case CKK_EC: + signature_length = MAX_ECKEY_LEN * 2; + mech.mechanism = CKM_ECDSA; + break; +#endif + default: + return CKR_DEVICE_ERROR; + } + + /* Allocate space for signature data. */ + signature = (unsigned char *) PORT_ZAlloc(signature_length); + if (signature == NULL) { + return CKR_HOST_MEMORY; + } + + /* Sign the known hash using the private key. */ + crv = NSC_SignInit(hSession, &mech, privateKey->handle); + if (crv != CKR_OK) { + PORT_Free(signature); + return crv; + } + + crv = NSC_Sign(hSession, + known_digest, + PAIRWISE_DIGEST_LENGTH, + signature, + &signature_length); + if (crv != CKR_OK) { + PORT_Free(signature); + return crv; + } + + /* Verify the known hash using the public key. */ + crv = NSC_VerifyInit(hSession, &mech, publicKey->handle); + if (crv != CKR_OK) { + PORT_Free(signature); + return crv; + } + + crv = NSC_Verify(hSession, + known_digest, + PAIRWISE_DIGEST_LENGTH, + signature, + signature_length); + + /* Free signature data. */ + PORT_Free(signature); + + if ((crv == CKR_SIGNATURE_LEN_RANGE) || + (crv == CKR_SIGNATURE_INVALID)) { + return CKR_GENERAL_ERROR; + } + if (crv != CKR_OK) { + return crv; + } + } + + /**********************************************/ + /* Pairwise Consistency Check for Derivation */ + /**********************************************/ + + isDerivable = sftk_isTrue(privateKey, CKA_DERIVE); + + if (isDerivable) { + /* + * We are not doing consistency check for Diffie-Hellman Key - + * otherwise it would be here + * This is also true for Elliptic Curve Diffie-Hellman keys + * NOTE: EC keys are currently subjected to pairwise + * consistency check for signing/verification. + */ + /* + * FIPS 140-2 had the following pairwise consistency test for + * public and private keys used for key agreement: + * If the keys are used to perform key agreement, then the + * cryptographic module shall create a second, compatible + * key pair. The cryptographic module shall perform both + * sides of the key agreement algorithm and shall compare + * the resulting shared values. If the shared values are + * not equal, the test shall fail. + * This test was removed in Change Notice 3. + */ + + } + + return CKR_OK; +} /* NSC_GenerateKeyPair generates a public-key/private-key pair, * creating new key objects. */ @@ -3408,6 +3686,18 @@ ecgn_done: sftk_forceAttribute(publicKey,CKA_NEVER_EXTRACTABLE, &cktrue,sizeof(CK_BBOOL)); } + + /* Perform FIPS 140-2 pairwise consistency check. */ + crv = sftk_PairwiseConsistencyCheck(hSession, + publicKey, privateKey, key_type); + if (crv != CKR_OK) { + NSC_DestroyObject(hSession,publicKey->handle); + sftk_FreeObject(publicKey); + NSC_DestroyObject(hSession,privateKey->handle); + sftk_FreeObject(privateKey); + return crv; + } + *phPrivateKey = privateKey->handle; *phPublicKey = publicKey->handle; sftk_FreeObject(publicKey); @@ -3429,7 +3719,6 @@ static SECItem *sftk_PackagePrivateKey(SFTKObject *key, CK_RV *crvp) #ifdef NSS_ENABLE_ECC SECItem *fordebug; int savelen; - int i; #endif if(!key) { @@ -4415,7 +4704,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH); - status = sftk_PRF(&pms, "master secret", &crsr, &master, isFIPS); + status = TLS_PRF(&pms, "master secret", &crsr, &master, isFIPS); if (status != SECSuccess) { crv = CKR_FUNCTION_FAILED; break; @@ -4546,7 +4835,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, ssl3_keys->RandomInfo.pClientRandom, SSL3_RANDOM_LENGTH); - status = sftk_PRF(&master, "key expansion", &srcr, &keyblk, + status = TLS_PRF(&master, "key expansion", &srcr, &keyblk, isFIPS); if (status != SECSuccess) { goto key_and_mac_derive_fail; @@ -4753,7 +5042,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, i += effKeySize; keyblk.data = key_block2; keyblk.len = sizeof key_block2; - status = sftk_PRF(&secret, "client write key", &crsr, &keyblk, + status = TLS_PRF(&secret, "client write key", &crsr, &keyblk, isFIPS); if (status != SECSuccess) { goto key_and_mac_derive_fail; @@ -4775,7 +5064,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, i += effKeySize; keyblk.data = key_block2; keyblk.len = sizeof key_block2; - status = sftk_PRF(&secret, "server write key", &crsr, &keyblk, + status = TLS_PRF(&secret, "server write key", &crsr, &keyblk, isFIPS); if (status != SECSuccess) { goto key_and_mac_derive_fail; @@ -4797,7 +5086,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, secret.len = 0; keyblk.data = &key_block[i]; keyblk.len = 2 * IVSize; - status = sftk_PRF(&secret, "IV block", &crsr, &keyblk, + status = TLS_PRF(&secret, "IV block", &crsr, &keyblk, isFIPS); if (status != SECSuccess) { goto key_and_mac_derive_fail; diff --git a/security/nss/lib/softoken/pkcs11f.h b/security/nss/lib/softoken/pkcs11f.h index 4ade31aac..a6bc91f46 100644 --- a/security/nss/lib/softoken/pkcs11f.h +++ b/security/nss/lib/softoken/pkcs11f.h @@ -14,7 +14,7 @@ * The Original Code is the Netscape security libraries. * * The Initial Developer of the Original Code is - * Netscape Communications Corporation. + * RSA Security INC. * Portions created by the Initial Developer are Copyright (C) 1994-2000 * the Initial Developer. All Rights Reserved. * @@ -152,10 +152,10 @@ CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo) /* C_InitToken initializes a token. */ CK_PKCS11_FUNCTION_INFO(C_InitToken) #ifdef CK_NEED_ARG_LIST -( /* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */ +( CK_SLOT_ID slotID, /* ID of the token's slot */ - CK_CHAR_PTR pPin, /* the SO's initial PIN */ + CK_UTF8CHAR_PTR pPin, /* the SO's initial PIN */ CK_ULONG ulPinLen, /* length in bytes of the PIN */ CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */ ); @@ -167,7 +167,7 @@ CK_PKCS11_FUNCTION_INFO(C_InitPIN) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ - CK_CHAR_PTR pPin, /* the normal user's PIN */ + CK_UTF8CHAR_PTR pPin, /* the normal user's PIN */ CK_ULONG ulPinLen /* length in bytes of the PIN */ ); #endif @@ -178,9 +178,9 @@ CK_PKCS11_FUNCTION_INFO(C_SetPIN) #ifdef CK_NEED_ARG_LIST ( CK_SESSION_HANDLE hSession, /* the session's handle */ - CK_CHAR_PTR pOldPin, /* the old PIN */ + CK_UTF8CHAR_PTR pOldPin, /* the old PIN */ CK_ULONG ulOldLen, /* length of the old PIN */ - CK_CHAR_PTR pNewPin, /* the new PIN */ + CK_UTF8CHAR_PTR pNewPin, /* the new PIN */ CK_ULONG ulNewLen /* length of the new PIN */ ); #endif @@ -264,7 +264,7 @@ CK_PKCS11_FUNCTION_INFO(C_Login) ( CK_SESSION_HANDLE hSession, /* the session's handle */ CK_USER_TYPE userType, /* the user type */ - CK_CHAR_PTR pPin, /* the user's PIN */ + CK_UTF8CHAR_PTR pPin, /* the user's PIN */ CK_ULONG ulPinLen /* the length of the PIN */ ); #endif diff --git a/security/nss/lib/softoken/pkcs11i.h b/security/nss/lib/softoken/pkcs11i.h index de7f0f80c..0eaf5bf37 100644 --- a/security/nss/lib/softoken/pkcs11i.h +++ b/security/nss/lib/softoken/pkcs11i.h @@ -321,40 +321,60 @@ struct SFTKSessionStr { * as well as the reference count of session objects in that bucket * (head[]->refCount), objectLock protects all elements of the token * object hash table (tokObjects[], tokenIDCount, and tokenHashTable), - * and slotLock protects the remaining protected elements: - * password, isLoggedIn, ssoLoggedIn, and sessionCount + * slotLock protects the remaining protected elements: + * password, isLoggedIn, ssoLoggedIn, and sessionCount, + * and pwCheckLock serializes the key database password checks in + * NSC_SetPIN and NSC_Login. + * + * Each of the fields below has the following lifetime as commented + * next to the fields: + * invariant - This value is set when the slot is first created and + * never changed until it is destroyed. + * per load - This value is set when the slot is first created, or + * when the slot is used to open another directory. Between open and close + * this field does not change. + * variable - This value changes through the normal process of slot operation. + * - reset. The value of this variable is cleared during an open/close + * cycles. + * - preserved. The value of this variable is preserved over open/close + * cycles. */ struct SFTKSlotStr { - CK_SLOT_ID slotID; - PZLock *slotLock; - PZLock **sessionLock; - unsigned int numSessionLocks; - unsigned long sessionLockMask; - PZLock *objectLock; - SECItem *password; - PRBool hasTokens; - PRBool isLoggedIn; - PRBool ssoLoggedIn; - PRBool needLogin; - PRBool DB_loaded; - PRBool readOnly; - PRBool optimizeSpace; - NSSLOWCERTCertDBHandle *certDB; - NSSLOWKEYDBHandle *keyDB; - int minimumPinLen; - PRInt32 sessionIDCount; /* atomically incremented */ - int sessionIDConflict; /* not protected by a lock */ - int sessionCount; - PRInt32 rwSessionCount; /* set by atomic operations */ - int tokenIDCount; - int index; - PLHashTable *tokenHashTable; - SFTKObject **tokObjects; - unsigned int tokObjHashSize; - SFTKSession **head; - unsigned int sessHashSize; - char tokDescription[33]; - char slotDescription[64]; + CK_SLOT_ID slotID; /* invariant */ + PZLock *slotLock; /* invariant */ + PZLock **sessionLock; /* invariant */ + unsigned int numSessionLocks; /* invariant */ + unsigned long sessionLockMask; /* invariant */ + PZLock *objectLock; /* invariant */ + PRLock *pwCheckLock; /* invariant */ + SECItem *password; /* variable - reset */ + PRBool present; /* variable -set */ + PRBool hasTokens; /* per load */ + PRBool isLoggedIn; /* variable - reset */ + PRBool ssoLoggedIn; /* variable - reset */ + PRBool needLogin; /* per load */ + PRBool DB_loaded; /* per load */ + PRBool readOnly; /* per load */ + PRBool optimizeSpace; /* invariant */ + NSSLOWCERTCertDBHandle *certDB; /* per load */ + NSSLOWKEYDBHandle *keyDB; /* per load */ + int minimumPinLen; /* per load */ + PRInt32 sessionIDCount; /* atomically incremented */ + /* (preserved) */ + int sessionIDConflict; /* not protected by a lock */ + /* (preserved) */ + int sessionCount; /* variable - reset */ + PRInt32 rwSessionCount; /* set by atomic operations */ + /* (reset) */ + int tokenIDCount; /* variable - perserved */ + int index; /* invariant */ + PLHashTable *tokenHashTable; /* invariant */ + SFTKObject **tokObjects; /* variable - reset */ + unsigned int tokObjHashSize; /* invariant */ + SFTKSession **head; /* variable -reset */ + unsigned int sessHashSize; /* invariant */ + char tokDescription[33]; /* per load */ + char slotDescription[64]; /* invariant */ }; /* @@ -404,8 +424,10 @@ struct SFTKSSLMACInfoStr { #define SFTK_TOKEN_TYPE_CERT 0x70000000L #define SFTK_TOKEN_KRL_HANDLE (SFTK_TOKEN_MAGIC|SFTK_TOKEN_TYPE_CRL|1) -/* how big a password/pin we can deal with */ +/* how big (in bytes) a password/pin we can deal with */ #define SFTK_MAX_PIN 255 +/* minimum password/pin length (in Unicode characters) in FIPS mode */ +#define FIPS_MIN_PIN 7 /* slot ID's */ #define NETSCAPE_SLOT_ID 1 @@ -533,14 +555,21 @@ typedef struct sftk_parametersStr { SEC_BEGIN_PROTOS +/* shared functions between PKCS11.c and SFTKFIPS.c */ extern int nsf_init; extern CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS); extern CK_RV nsc_CommonFinalize(CK_VOID_PTR pReserved, PRBool isFIPS); extern CK_RV nsc_CommonGetSlotList(CK_BBOOL tokPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount, int moduleIndex); -/* shared functions between PKCS11.c and SFTKFIPS.c */ -extern CK_RV SFTK_SlotInit(char *configdir,sftk_token_parameters *params, - int moduleIndex); + +/* slot initialization, reinit, shutdown and destruction */ +extern CK_RV SFTK_SlotInit(char *configdir, + sftk_token_parameters *params, int moduleIndex); +extern CK_RV SFTK_SlotReInit(SFTKSlot *slot, char *configdir, + sftk_token_parameters *params, int moduleIndex); +extern CK_RV SFTK_DestroySlotData(SFTKSlot *slot); +extern CK_RV SFTK_ShutdownSlot(SFTKSlot *slot); + /* internal utility functions used by pkcs11.c */ extern SFTKAttribute *sftk_FindAttribute(SFTKObject *object, @@ -586,6 +615,9 @@ extern SFTKObject *sftk_ObjectFromHandle(CK_OBJECT_HANDLE handle, SFTKSession *session); extern void sftk_AddSlotObject(SFTKSlot *slot, SFTKObject *object); extern void sftk_AddObject(SFTKSession *session, SFTKObject *object); +/* clear out all the existing object ID to database key mappings. + * used to reinit a token */ +extern CK_RV SFTK_ClearTokenKeyHashTable(SFTKSlot *slot); extern CK_RV sftk_searchObjectList(SFTKSearchResults *search, SFTKObject **head, unsigned int size, @@ -597,7 +629,7 @@ extern void sftk_FreeObjectList(SFTKObjectListElement *objectList); extern void sftk_FreeSearch(SFTKSearchResults *search); extern CK_RV sftk_handleObject(SFTKObject *object, SFTKSession *session); -extern SFTKSlot *sftk_SlotFromID(CK_SLOT_ID slotID); +extern SFTKSlot *sftk_SlotFromID(CK_SLOT_ID slotID, PRBool all); extern SFTKSlot *sftk_SlotFromSessionHandle(CK_SESSION_HANDLE handle); extern SFTKSession *sftk_SessionFromHandle(CK_SESSION_HANDLE handle); extern void sftk_FreeSession(SFTKSession *session); @@ -653,9 +685,14 @@ CK_RV sftk_DBInit(const char *configdir, const char *certPrefix, const char *keyPrefix, PRBool readOnly, PRBool noCertDB, PRBool noKeyDB, PRBool forceOpen, NSSLOWCERTCertDBHandle **certDB, NSSLOWKEYDBHandle **keyDB); +NSSLOWCERTCertDBHandle *sftk_getCertDB(SFTKSlot *slot); +NSSLOWKEYDBHandle *sftk_getKeyDB(SFTKSlot *slot); +void sftk_freeCertDB(NSSLOWCERTCertDBHandle *certHandle); +void sftk_freeKeyDB(NSSLOWKEYDBHandle *keyHandle); -void sftk_DBShutdown(NSSLOWCERTCertDBHandle *certHandle, - NSSLOWKEYDBHandle *keyHandle); +/* helper function which calls nsslowkey_FindKeyByPublicKey after safely + * acquiring a reference to the keydb from the slot */ +NSSLOWKEYPrivateKey *sftk_FindKeyByPublicKey(SFTKSlot *slot, SECItem *dbKey); const char *sftk_EvaluateConfigDir(const char *configdir, char **domain); @@ -683,10 +720,6 @@ SFTKTokenObject *sftk_convertSessionToToken(SFTKObject *so); * implement TLS Pseudo Random Function (PRF) */ -extern SECStatus -sftk_PRF(const SECItem *secret, const char *label, SECItem *seed, - SECItem *result, PRBool isFIPS); - extern CK_RV sftk_TLSPRFInit(SFTKSessionContext *context, SFTKObject * key, diff --git a/security/nss/lib/softoken/pkcs11n.h b/security/nss/lib/softoken/pkcs11n.h index 31137c4d2..b1dce6c12 100644 --- a/security/nss/lib/softoken/pkcs11n.h +++ b/security/nss/lib/softoken/pkcs11n.h @@ -73,6 +73,8 @@ static const char CKT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$"; #define CKO_NETSCAPE_SMIME (CKO_NETSCAPE + 2) #define CKO_NETSCAPE_TRUST (CKO_NETSCAPE + 3) #define CKO_NETSCAPE_BUILTIN_ROOT_LIST (CKO_NETSCAPE + 4) +#define CKO_NETSCAPE_NEWSLOT (CKO_NETSCAPE + 5) +#define CKO_NETSCAPE_DELSLOT (CKO_NETSCAPE + 6) /* * Netscape-defined key types @@ -106,6 +108,7 @@ static const char CKT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$"; #define CKA_NETSCAPE_PQG_SEED (CKA_NETSCAPE + 21) #define CKA_NETSCAPE_PQG_H (CKA_NETSCAPE + 22) #define CKA_NETSCAPE_PQG_SEED_BITS (CKA_NETSCAPE + 23) +#define CKA_NETSCAPE_MODULE_SPEC (CKA_NETSCAPE + 24) /* * Trust attributes: @@ -233,4 +236,11 @@ typedef CK_ULONG CK_TRUST; typedef char ** (PR_CALLBACK *SECMODModuleDBFunc)(unsigned long function, char *parameters, void *moduleSpec); +/* softoken slot ID's */ +#define SFTK_MIN_USER_SLOT_ID 4 +#define SFTK_MAX_USER_SLOT_ID 100 +#define SFTK_MIN_FIPS_USER_SLOT_ID 101 +#define SFTK_MAX_FIPS_USER_SLOT_ID 127 + + #endif /* _PKCS11N_H_ */ diff --git a/security/nss/lib/softoken/pkcs11ni.h b/security/nss/lib/softoken/pkcs11ni.h new file mode 100644 index 000000000..9e584a9f0 --- /dev/null +++ b/security/nss/lib/softoken/pkcs11ni.h @@ -0,0 +1,52 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Red Hat, Inc. + * Portions created by the Initial Developer are Copyright (C) 2005 + * the Initial Developer. All Rights Reserved. + * + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _PKCS11NI_H_ +#define _PKCS11NI_H_ + +/* + * pkcs11ni.h + * + * This file contains softoken private exports for NSS + */ + +/* softoken slot ID's */ +#define SFTK_MIN_USER_SLOT_ID 4 +#define SFTK_MAX_USER_SLOT_ID 100 +#define SFTK_MIN_FIPS_USER_SLOT_ID 101 +#define SFTK_MAX_FIPS_USER_SLOT_ID 127 + + +#endif /* _PKCS11NI_H_ */ diff --git a/security/nss/lib/softoken/pkcs11t.h b/security/nss/lib/softoken/pkcs11t.h index f3761f6b5..771f65ab2 100644 --- a/security/nss/lib/softoken/pkcs11t.h +++ b/security/nss/lib/softoken/pkcs11t.h @@ -14,7 +14,7 @@ * The Original Code is the Netscape security libraries. * * The Initial Developer of the Original Code is - * Netscape Communications Corporation. + * RSA Security, Inc. * Portions created by the Initial Developer are Copyright (C) 1994-2000 * the Initial Developer. All Rights Reserved. * @@ -34,27 +34,27 @@ * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ -/* - * Copyright (C) 1994-1999 RSA Security Inc. Licence to copy this document - * is granted provided that it is identified as "RSA Security In.c Public-Key - * Cryptography Standards (PKCS)" in all material mentioning or referencing - * this document. - */ -/* See top of pkcs11.h for information about the macros that - * must be defined and the structure-packing conventions that - * must be set before including this file. +/* License to copy and use this software is granted provided that it is + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface + * (Cryptoki)" in all material mentioning or referencing this software. + + * License is also granted to make and use derivative works provided that + * such works are identified as "derived from the RSA Security Inc. PKCS #11 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or + * referencing the derived work. + + * RSA Security Inc. makes no representations concerning either the + * merchantability of this software or the suitability of this software for + * any particular purpose. It is provided "as is" without express or implied + * warranty of any kind. */ + #ifndef _PKCS11T_H_ #define _PKCS11T_H_ 1 -#ifndef CK_FALSE -#define CK_FALSE 0 -#endif - -#ifndef CK_TRUE -#define CK_TRUE (!CK_FALSE) -#endif +#define CK_TRUE 1 +#define CK_FALSE 0 #include "prtypes.h" @@ -64,7 +64,7 @@ #define CK_DECLARE_FUNCTION(rv,func) PR_EXTERN(rv) func #define CK_DECLARE_FUNCTION_POINTER(rv,func) rv (PR_CALLBACK * func) -#define CK_INVALID_SESSION 0 +#define CK_INVALID_SESSION 0 /* an unsigned 8-bit value */ typedef unsigned char CK_BYTE; @@ -72,7 +72,7 @@ typedef unsigned char CK_BYTE; /* an unsigned 8-bit character */ typedef CK_BYTE CK_CHAR; -/* an unsigned 8-bit character */ +/* an 8-bit UTF-8 character */ typedef CK_BYTE CK_UTF8CHAR; /* a BYTE-sized Boolean flag */ @@ -121,8 +121,8 @@ typedef CK_VERSION CK_PTR CK_VERSION_PTR; typedef struct CK_INFO { - /* manufacturerID and libraryDecription have been changed from - * CK_CHAR to CK_UTF8CHAR for v2.10 */ + /* manufacturerID and libraryDecription have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ CK_VERSION cryptokiVersion; /* PKCS #11 interface ver */ CK_UTF8CHAR manufacturerID[32]; /* blank padded */ CK_FLAGS flags; /* must be zero */ @@ -150,8 +150,8 @@ typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR; /* CK_SLOT_INFO provides information about a slot */ typedef struct CK_SLOT_INFO { - /* slotDescription and manufacturerID have been changed from - * CK_CHAR to CK_UTF8CHAR for v2.10 */ + /* slotDescription and manufacturerID have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ CK_UTF8CHAR slotDescription[64]; /* blank padded */ CK_UTF8CHAR manufacturerID[32]; /* blank padded */ CK_FLAGS flags; @@ -173,8 +173,8 @@ typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR; /* CK_TOKEN_INFO provides information about a token */ typedef struct CK_TOKEN_INFO { - /* label, manufacturerID, and model have been changed from - * CK_CHAR to CK_UTF8CHAR for v2.10 */ + /* label, manufacturerID, and model have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ CK_UTF8CHAR label[32]; /* blank padded */ CK_UTF8CHAR manufacturerID[32]; /* blank padded */ CK_UTF8CHAR model[16]; /* blank padded */ @@ -203,7 +203,7 @@ typedef struct CK_TOKEN_INFO { } CK_TOKEN_INFO; /* The flags parameter is defined as follows: - * Bit Flag Mask Meaning + * Bit Flag Mask Meaning */ #define CKF_RNG 0x00000001 /* has random # * generator */ @@ -239,20 +239,20 @@ typedef struct CK_TOKEN_INFO { #define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200 /* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the - * token has been initialized using C_InitializeToken or an + * token has been initialized using C_InitializeToken or an * equivalent mechanism outside the scope of PKCS #11. - * Calling C_InitializeToken when this flag is set will cause + * Calling C_InitializeToken when this flag is set will cause * the token to be reinitialized. */ #define CKF_TOKEN_INITIALIZED 0x00000400 -/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is - * true, the token supports secondary authentication for - * private key objects. */ -/* DEPRICATED in v2.11 */ +/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is + * true, the token supports secondary authentication for + * private key objects. This flag is deprecated in v2.11 and + onwards. */ #define CKF_SECONDARY_AUTHENTICATION 0x00000800 -/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an - * incorrect user login PIN has been entered at least once +/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an + * incorrect user login PIN has been entered at least once * since the last successful authentication. */ #define CKF_USER_PIN_COUNT_LOW 0x00010000 @@ -260,18 +260,19 @@ typedef struct CK_TOKEN_INFO { * supplying an incorrect user PIN will it to become locked. */ #define CKF_USER_PIN_FINAL_TRY 0x00020000 -/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the - * user PIN has been locked. User login to the token is not +/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the + * user PIN has been locked. User login to the token is not * possible. */ #define CKF_USER_PIN_LOCKED 0x00040000 -/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true, - * the user PIN value is the default value set by token - * initialization or manufacturing. */ +/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true, + * the user PIN value is the default value set by token + * initialization or manufacturing, or the PIN has been + * expired by the card. */ #define CKF_USER_PIN_TO_BE_CHANGED 0x00080000 -/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an - * incorrect SO login PIN has been entered at least once since +/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an + * incorrect SO login PIN has been entered at least once since * the last successful authentication. */ #define CKF_SO_PIN_COUNT_LOW 0x00100000 @@ -279,14 +280,15 @@ typedef struct CK_TOKEN_INFO { * supplying an incorrect SO PIN will it to become locked. */ #define CKF_SO_PIN_FINAL_TRY 0x00200000 -/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO +/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO * PIN has been locked. SO login to the token is not possible. */ #define CKF_SO_PIN_LOCKED 0x00400000 -/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true, - * the SO PIN value is the default value set by token - * initialization or manufacturing. */ +/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true, + * the SO PIN value is the default value set by token + * initialization or manufacturing, or the PIN has been + * expired by the card. */ #define CKF_SO_PIN_TO_BE_CHANGED 0x00800000 typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR; @@ -296,7 +298,7 @@ typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR; * identifies a session */ typedef CK_ULONG CK_SESSION_HANDLE; -typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR; +typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR; /* CK_USER_TYPE enumerates the types of PKCS #11 users */ @@ -307,7 +309,8 @@ typedef CK_ULONG CK_USER_TYPE; #define CKU_SO 0 /* Normal user */ #define CKU_USER 1 - +/* Context specific (added in v2.20) */ +#define CKU_CONTEXT_SPECIFIC 2 /* CK_STATE enumerates the session states */ /* CK_STATE has been changed from an enum to a CK_ULONG for @@ -357,6 +360,7 @@ typedef CK_ULONG CK_OBJECT_CLASS; /* The following classes of objects are defined: */ /* CKO_HW_FEATURE is new for v2.10 */ /* CKO_DOMAIN_PARAMETERS is new for v2.11 */ +/* CKO_MECHANISM is new for v2.20 */ #define CKO_DATA 0x00000000 #define CKO_CERTIFICATE 0x00000001 #define CKO_PUBLIC_KEY 0x00000002 @@ -364,7 +368,7 @@ typedef CK_ULONG CK_OBJECT_CLASS; #define CKO_SECRET_KEY 0x00000004 #define CKO_HW_FEATURE 0x00000005 #define CKO_DOMAIN_PARAMETERS 0x00000006 -#define CKO_KG_PARAMETERS 0x00000006 +#define CKO_MECHANISM 0x00000007 #define CKO_VENDOR_DEFINED 0x80000000 typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR; @@ -373,10 +377,12 @@ typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR; * value that identifies the hardware feature type of an object * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */ typedef CK_ULONG CK_HW_FEATURE_TYPE; - + /* The following hardware feature types are defined */ +/* CKH_USER_INTERFACE is new for v2.20 */ #define CKH_MONOTONIC_COUNTER 0x00000001 #define CKH_CLOCK 0x00000002 +#define CKH_USER_INTERFACE 0x00000003 #define CKH_VENDOR_DEFINED 0x80000000 /* CK_KEY_TYPE is a value that identifies a key type */ @@ -389,10 +395,10 @@ typedef CK_ULONG CK_KEY_TYPE; #define CKK_DH 0x00000002 /* CKK_ECDSA and CKK_KEA are new for v2.0 */ -/* CKK_X9_42_DH is new for v2.11 */ -#define CKK_ECDSA 0x00000003 /* deprecated in v2.11 */ +/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */ +#define CKK_ECDSA 0x00000003 #define CKK_EC 0x00000003 -#define CKK_X9_42_DH 0x00000004 +#define CKK_X9_42_DH 0x00000004 #define CKK_KEA 0x00000005 #define CKK_GENERIC_SECRET 0x00000010 @@ -405,7 +411,8 @@ typedef CK_ULONG CK_KEY_TYPE; /* all these key types are new for v2.0 */ #define CKK_CAST 0x00000016 #define CKK_CAST3 0x00000017 -#define CKK_CAST5 0x00000018 /* deprecated in v2.11 */ +/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */ +#define CKK_CAST5 0x00000018 #define CKK_CAST128 0x00000018 #define CKK_RC5 0x00000019 #define CKK_IDEA 0x0000001A @@ -413,12 +420,13 @@ typedef CK_ULONG CK_KEY_TYPE; #define CKK_BATON 0x0000001C #define CKK_JUNIPER 0x0000001D #define CKK_CDMF 0x0000001E - -/* all these key types are new for v2.11 */ #define CKK_AES 0x0000001F +/* BlowFish and TwoFish are new for v2.20 */ +#define CKK_BLOWFISH 0x00000020 +#define CKK_TWOFISH 0x00000021 + #define CKK_VENDOR_DEFINED 0x80000000 -#define CKK_INVALID_KEY_TYPE 0xffffffff /* CK_CERTIFICATE_TYPE is a value that identifies a certificate @@ -429,8 +437,10 @@ typedef CK_ULONG CK_CERTIFICATE_TYPE; /* The following certificate types are defined: */ /* CKC_X_509_ATTR_CERT is new for v2.10 */ +/* CKC_WTLS is new for v2.20 */ #define CKC_X_509 0x00000000 #define CKC_X_509_ATTR_CERT 0x00000001 +#define CKC_WTLS 0x00000002 #define CKC_VENDOR_DEFINED 0x80000000 @@ -440,6 +450,10 @@ typedef CK_ULONG CK_CERTIFICATE_TYPE; * v2.0 */ typedef CK_ULONG CK_ATTRIBUTE_TYPE; +/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which + consists of an array of values. */ +#define CKF_ARRAY_ATTRIBUTE 0x40000000 + /* The following attribute types are defined: */ #define CKA_CLASS 0x00000000 #define CKA_TOKEN 0x00000001 @@ -455,14 +469,24 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE; #define CKA_ISSUER 0x00000081 #define CKA_SERIAL_NUMBER 0x00000082 -/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new +/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new * for v2.10 */ #define CKA_AC_ISSUER 0x00000083 #define CKA_OWNER 0x00000084 #define CKA_ATTR_TYPES 0x00000085 + /* CKA_TRUSTED is new for v2.11 */ #define CKA_TRUSTED 0x00000086 +/* CKA_CERTIFICATE_CATEGORY ... + * CKA_CHECK_VALUE are new for v2.20 */ +#define CKA_CERTIFICATE_CATEGORY 0x00000087 +#define CKA_JAVA_MIDP_SECURITY_DOMAIN 0x00000088 +#define CKA_URL 0x00000089 +#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY 0x0000008A +#define CKA_HASH_OF_ISSUER_PUBLIC_KEY 0x0000008B +#define CKA_CHECK_VALUE 0x00000090 + #define CKA_KEY_TYPE 0x00000100 #define CKA_SUBJECT 0x00000101 #define CKA_ID 0x00000102 @@ -490,9 +514,13 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE; #define CKA_PRIME 0x00000130 #define CKA_SUBPRIME 0x00000131 #define CKA_BASE 0x00000132 + /* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */ #define CKA_PRIME_BITS 0x00000133 -#define CKA_SUB_PRIME_BITS 0x00000134 +#define CKA_SUBPRIME_BITS 0x00000134 +#define CKA_SUB_PRIME_BITS CKA_SUBPRIME_BITS +/* (To retain backwards-compatibility) */ + #define CKA_VALUE_BITS 0x00000160 #define CKA_VALUE_LEN 0x00000161 @@ -503,22 +531,55 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE; #define CKA_LOCAL 0x00000163 #define CKA_NEVER_EXTRACTABLE 0x00000164 #define CKA_ALWAYS_SENSITIVE 0x00000165 + /* CKA_KEY_GEN_MECHANISM is new for v2.11 */ #define CKA_KEY_GEN_MECHANISM 0x00000166 + #define CKA_MODIFIABLE 0x00000170 -#define CKA_ECDSA_PARAMS 0x00000180 /* depricated v2.11 */ + +/* CKA_ECDSA_PARAMS is deprecated in v2.11, + * CKA_EC_PARAMS is preferred. */ +#define CKA_ECDSA_PARAMS 0x00000180 #define CKA_EC_PARAMS 0x00000180 + #define CKA_EC_POINT 0x00000181 -/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS, - * CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET +/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS, + * are new for v2.10. Deprecated in v2.11 and onwards. */ +#define CKA_SECONDARY_AUTH 0x00000200 +#define CKA_AUTH_PIN_FLAGS 0x00000201 + +/* CKA_ALWAYS_AUTHENTICATE ... + * CKA_UNWRAP_TEMPLATE are new for v2.20 */ +#define CKA_ALWAYS_AUTHENTICATE 0x00000202 + +#define CKA_WRAP_WITH_TRUSTED 0x00000210 +#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000211) +#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE|0x00000212) + +/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET * are new for v2.10 */ -#define CKA_SECONDARY_AUTH 0x00000200 /* depricated v2.11 */ -#define CKA_AUTH_PIN_FLAGS 0x00000201 /* depricated v2.11 */ #define CKA_HW_FEATURE_TYPE 0x00000300 #define CKA_RESET_ON_INIT 0x00000301 #define CKA_HAS_RESET 0x00000302 +/* The following attributes are new for v2.20 */ +#define CKA_PIXEL_X 0x00000400 +#define CKA_PIXEL_Y 0x00000401 +#define CKA_RESOLUTION 0x00000402 +#define CKA_CHAR_ROWS 0x00000403 +#define CKA_CHAR_COLUMNS 0x00000404 +#define CKA_COLOR 0x00000405 +#define CKA_BITS_PER_PIXEL 0x00000406 +#define CKA_CHAR_SETS 0x00000480 +#define CKA_ENCODING_METHODS 0x00000481 +#define CKA_MIME_TYPES 0x00000482 +#define CKA_MECHANISM_TYPE 0x00000500 +#define CKA_REQUIRED_CMS_ATTRIBUTES 0x00000501 +#define CKA_DEFAULT_CMS_ATTRIBUTES 0x00000502 +#define CKA_SUPPORTED_CMS_ATTRIBUTES 0x00000503 +#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600) + #define CKA_VENDOR_DEFINED 0x80000000 @@ -561,17 +622,19 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_MD5_RSA_PKCS 0x00000005 #define CKM_SHA1_RSA_PKCS 0x00000006 -/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS & CKM_RSA_OAEP - * are new for 2.10 */ +/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and + * CKM_RSA_PKCS_OAEP are new for v2.10 */ #define CKM_RIPEMD128_RSA_PKCS 0x00000007 #define CKM_RIPEMD160_RSA_PKCS 0x00000008 #define CKM_RSA_PKCS_OAEP 0x00000009 -/* CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31 & CKM_RSA_X9_31_KEY_PAIR_GEN - * are new for 2.11 */ +/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31, + * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */ #define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A #define CKM_RSA_X9_31 0x0000000B #define CKM_SHA1_RSA_X9_31 0x0000000C +#define CKM_RSA_PKCS_PSS 0x0000000D +#define CKM_SHA1_RSA_PKCS_PSS 0x0000000E #define CKM_DSA_KEY_PAIR_GEN 0x00000010 #define CKM_DSA 0x00000011 @@ -579,17 +642,21 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020 #define CKM_DH_PKCS_DERIVE 0x00000021 -/* CKM_X9_42_DH_PKCS_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE, - * CKM_X9_42_DH_HYBRID_DERIVE, & CKM_X9_42_MQV_DERIVE - * are new for v2.11 */ -#define CKM_X9_42_DH_PKCS_KEY_PAIR_GEN 0x00000030 +/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE, + * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for + * v2.11 */ +#define CKM_X9_42_DH_KEY_PAIR_GEN 0x00000030 #define CKM_X9_42_DH_DERIVE 0x00000031 #define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032 #define CKM_X9_42_MQV_DERIVE 0x00000033 -#define CKM_SHA256_RSA_PKCS 0x00000040 /* v2.20 */ -#define CKM_SHA384_RSA_PKCS 0x00000041 /* v2.20 */ -#define CKM_SHA512_RSA_PKCS 0x00000042 /* v2.20 */ +/* CKM_SHA256/384/512 are new for v2.20 */ +#define CKM_SHA256_RSA_PKCS 0x00000040 +#define CKM_SHA384_RSA_PKCS 0x00000041 +#define CKM_SHA512_RSA_PKCS 0x00000042 +#define CKM_SHA256_RSA_PKCS_PSS 0x00000043 +#define CKM_SHA384_RSA_PKCS_PSS 0x00000044 +#define CKM_SHA512_RSA_PKCS_PSS 0x00000045 #define CKM_RC2_KEY_GEN 0x00000100 #define CKM_RC2_ECB 0x00000101 @@ -629,6 +696,12 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_CDMF_MAC_GENERAL 0x00000144 #define CKM_CDMF_CBC_PAD 0x00000145 +/* the following four DES mechanisms are new for v2.20 */ +#define CKM_DES_OFB64 0x00000150 +#define CKM_DES_OFB8 0x00000151 +#define CKM_DES_CFB64 0x00000152 +#define CKM_DES_CFB8 0x00000153 + #define CKM_MD2 0x00000200 /* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */ @@ -647,7 +720,7 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_SHA_1_HMAC 0x00000221 #define CKM_SHA_1_HMAC_GENERAL 0x00000222 -/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC, +/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC, * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC, * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */ #define CKM_RIPEMD128 0x00000230 @@ -657,17 +730,16 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_RIPEMD160_HMAC 0x00000241 #define CKM_RIPEMD160_HMAC_GENERAL 0x00000242 -#define CKM_SHA256 0x00000250 /* v2.20 */ -#define CKM_SHA256_HMAC 0x00000251 /* v2.20 */ -#define CKM_SHA256_HMAC_GENERAL 0x00000252 /* v2.20 */ - -#define CKM_SHA384 0x00000260 /* v2.20 */ -#define CKM_SHA384_HMAC 0x00000261 /* v2.20 */ -#define CKM_SHA384_HMAC_GENERAL 0x00000262 /* v2.20 */ - -#define CKM_SHA512 0x00000270 /* v2.20 */ -#define CKM_SHA512_HMAC 0x00000271 /* v2.20 */ -#define CKM_SHA512_HMAC_GENERAL 0x00000272 /* v2.20 */ +/* CKM_SHA256/384/512 are new for v2.20 */ +#define CKM_SHA256 0x00000250 +#define CKM_SHA256_HMAC 0x00000251 +#define CKM_SHA256_HMAC_GENERAL 0x00000252 +#define CKM_SHA384 0x00000260 +#define CKM_SHA384_HMAC 0x00000261 +#define CKM_SHA384_HMAC_GENERAL 0x00000262 +#define CKM_SHA512 0x00000270 +#define CKM_SHA512_HMAC 0x00000271 +#define CKM_SHA512_HMAC_GENERAL 0x00000272 /* All of the following mechanisms are new for v2.0 */ /* Note that CAST128 and CAST5 are the same algorithm */ @@ -718,23 +790,27 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372 /* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN, - * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, - * CKM_TLS_MASTER_KEY_DERIVE_DH, & CKM_SSL3_MASTER_KEY_DERIVE_DH - * are new for v2.11. */ + * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and + * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */ #define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373 #define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374 #define CKM_TLS_MASTER_KEY_DERIVE 0x00000375 #define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376 #define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377 +/* CKM_TLS_PRF is new for v2.20 */ +#define CKM_TLS_PRF 0x00000378 + #define CKM_SSL3_MD5_MAC 0x00000380 #define CKM_SSL3_SHA1_MAC 0x00000381 #define CKM_MD5_KEY_DERIVATION 0x00000390 #define CKM_MD2_KEY_DERIVATION 0x00000391 #define CKM_SHA1_KEY_DERIVATION 0x00000392 -#define CKM_SHA256_KEY_DERIVATION 0x00000393 /* v2.20 */ -#define CKM_SHA384_KEY_DERIVATION 0x00000394 /* v2.20 */ -#define CKM_SHA512_KEY_DERIVATION 0x00000395 /* v2.20 */ + +/* CKM_SHA256/384/512 are new for v2.20 */ +#define CKM_SHA256_KEY_DERIVATION 0x00000393 +#define CKM_SHA384_KEY_DERIVATION 0x00000394 +#define CKM_SHA512_KEY_DERIVATION 0x00000395 #define CKM_PBE_MD2_DES_CBC 0x000003A0 #define CKM_PBE_MD5_DES_CBC 0x000003A1 @@ -755,9 +831,21 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_PKCS5_PBKD2 0x000003B0 #define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0 + +/* WTLS mechanisms are new for v2.20 */ +#define CKM_WTLS_PRE_MASTER_KEY_GEN 0x000003D0 +#define CKM_WTLS_MASTER_KEY_DERIVE 0x000003D1 +#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC 0x000003D2 +#define CKM_WTLS_PRF 0x000003D3 +#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE 0x000003D4 +#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE 0x000003D5 + #define CKM_KEY_WRAP_LYNKS 0x00000400 #define CKM_KEY_WRAP_SET_OAEP 0x00000401 +/* CKM_CMS_SIG is new for v2.20 */ +#define CKM_CMS_SIG 0x00000500 + /* Fortezza mechanisms */ #define CKM_SKIPJACK_KEY_GEN 0x00001000 #define CKM_SKIPJACK_ECB64 0x00001001 @@ -780,12 +868,17 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_BATON_COUNTER 0x00001034 #define CKM_BATON_SHUFFLE 0x00001035 #define CKM_BATON_WRAP 0x00001036 -#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 /* depricated in v2.11 */ + +/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11, + * CKM_EC_KEY_PAIR_GEN is preferred */ +#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 #define CKM_EC_KEY_PAIR_GEN 0x00001040 + #define CKM_ECDSA 0x00001041 #define CKM_ECDSA_SHA1 0x00001042 -/* ECDH1 is new for 2.11 */ +/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE + * are new for v2.11 */ #define CKM_ECDH1_DERIVE 0x00001050 #define CKM_ECDH1_COFACTOR_DERIVE 0x00001051 #define CKM_ECMQV_DERIVE 0x00001052 @@ -798,7 +891,10 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_JUNIPER_WRAP 0x00001065 #define CKM_FASTHASH 0x00001070 -/* AES is new for 2.11 */ +/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC, + * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN, + * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are + * new for v2.11 */ #define CKM_AES_KEY_GEN 0x00001080 #define CKM_AES_ECB 0x00001081 #define CKM_AES_CBC 0x00001082 @@ -806,11 +902,24 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_AES_MAC_GENERAL 0x00001084 #define CKM_AES_CBC_PAD 0x00001085 -/* CKM_DSA_PARAMETER_GEN, CKM_DH_PKCS_PARAMETER_GEN, - * and CKM_DH_X9_42_PARAMETER_GEN are new for 2.11 */ +/* BlowFish and TwoFish are new for v2.20 */ +#define CKM_BLOWFISH_KEY_GEN 0x00001090 +#define CKM_BLOWFISH_CBC 0x00001091 +#define CKM_TWOFISH_KEY_GEN 0x00001092 +#define CKM_TWOFISH_CBC 0x00001093 + + +/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */ +#define CKM_DES_ECB_ENCRYPT_DATA 0x00001100 +#define CKM_DES_CBC_ENCRYPT_DATA 0x00001101 +#define CKM_DES3_ECB_ENCRYPT_DATA 0x00001102 +#define CKM_DES3_CBC_ENCRYPT_DATA 0x00001103 +#define CKM_AES_ECB_ENCRYPT_DATA 0x00001104 +#define CKM_AES_CBC_ENCRYPT_DATA 0x00001105 + #define CKM_DSA_PARAMETER_GEN 0x00002000 #define CKM_DH_PKCS_PARAMETER_GEN 0x00002001 -#define CKM_DH_X9_42_PARAMETER_GEN 0x00002002 +#define CKM_X9_42_DH_PARAMETER_GEN 0x00002002 #define CKM_VENDOR_DEFINED 0x80000000 @@ -848,8 +957,6 @@ typedef struct CK_MECHANISM_INFO { * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP, * and CKF_DERIVE are new for v2.0. They specify whether or not * a mechanism can be used for a particular task */ -/* The flags CKF_EC_FP, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE, - * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11 */ #define CKF_ENCRYPT 0x00000100 #define CKF_DECRYPT 0x00000200 #define CKF_DIGEST 0x00000400 @@ -862,14 +969,19 @@ typedef struct CK_MECHANISM_INFO { #define CKF_WRAP 0x00020000 #define CKF_UNWRAP 0x00040000 #define CKF_DERIVE 0x00080000 -#define CKF_EC_FP 0x00100000 + +/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE, + * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They + * describe a token's EC capabilities not available in mechanism + * information. */ +#define CKF_EC_F_P 0x00100000 #define CKF_EC_F_2M 0x00200000 #define CKF_EC_ECPARAMETERS 0x00400000 #define CKF_EC_NAMEDCURVE 0x00800000 #define CKF_EC_UNCOMPRESS 0x01000000 #define CKF_EC_COMPRESS 0x02000000 -#define CKF_EXTENSION 0x80000000 /* FALSE for 2.01 */ +#define CKF_EXTENSION 0x80000000 /* FALSE for this version */ typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR; @@ -933,9 +1045,6 @@ typedef CK_ULONG CK_RV; #define CKR_KEY_NOT_WRAPPABLE 0x00000069 #define CKR_KEY_UNEXTRACTABLE 0x0000006A -/* CKR_KEY_PARAMS_INVALID is new for v2.11 */ -#define CKR_KEY_PARAMS_INVALID 0x0000006B - #define CKR_MECHANISM_INVALID 0x00000070 #define CKR_MECHANISM_PARAM_INVALID 0x00000071 @@ -991,10 +1100,10 @@ typedef CK_ULONG CK_RV; #define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115 #define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120 -/* New for v2.0 */ +/* These are new to v2.0 */ #define CKR_RANDOM_NO_RNG 0x00000121 -/* New for v2.11 */ +/* These are new to v2.11 */ #define CKR_DOMAIN_PARAMS_INVALID 0x00000130 /* These are new to v2.0 */ @@ -1009,6 +1118,9 @@ typedef CK_ULONG CK_RV; #define CKR_MUTEX_BAD 0x000001A0 #define CKR_MUTEX_NOT_LOCKED 0x000001A1 +/* This is new to v2.20 */ +#define CKR_FUNCTION_REJECTED 0x00000200 + #define CKR_VENDOR_DEFINED 0x80000000 @@ -1066,7 +1178,17 @@ typedef struct CK_C_INITIALIZE_ARGS { CK_LOCKMUTEX LockMutex; CK_UNLOCKMUTEX UnlockMutex; CK_FLAGS flags; + /* The official PKCS #11 spec does not have a 'LibraryParameters' field, but + * a reserved field. NSS needs a way to pass instance-specific information + * to the library (like where to find its config files, etc). This + * information is usually provided by the installer and passed uninterpreted + * by NSS to the library, though NSS does know the specifics of the softoken + * version of this parameter. Most compliant PKCS#11 modules expect this + * parameter to be NULL, and will return CKR_ARGUMENTS_BAD from + * C_Initialize if Library parameters is supplied. */ CK_CHAR_PTR *LibraryParameters; + /* This field is only present if the LibraryParameters is not NULL. It must + * be NULL in all cases */ CK_VOID_PTR pReserved; } CK_C_INITIALIZE_ARGS; @@ -1084,21 +1206,26 @@ typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR; /* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */ #define CKF_DONT_BLOCK 1 -/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10. - * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message - * Generation Function (MGF) applied to a message block when - * formatting a message block for the PKCS #1 OAEP encryption +/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10. + * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message + * Generation Function (MGF) applied to a message block when + * formatting a message block for the PKCS #1 OAEP encryption * scheme. */ -typedef CK_ULONG CK_RSA_PKCS_OAEP_MGF_TYPE; +typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE; -typedef CK_RSA_PKCS_OAEP_MGF_TYPE CK_PTR CK_RSA_PKCS_OAEP_MGF_TYPE_PTR; +typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR; /* The following MGFs are defined */ +/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512 + * are new for v2.20 */ #define CKG_MGF1_SHA1 0x00000001 +#define CKG_MGF1_SHA256 0x00000002 +#define CKG_MGF1_SHA384 0x00000003 +#define CKG_MGF1_SHA512 0x00000004 -/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10. +/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10. * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source - * of the encoding parameter when formatting a message block + * of the encoding parameter when formatting a message block * for the PKCS #1 OAEP encryption scheme. */ typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE; @@ -1108,18 +1235,141 @@ typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR; #define CKZ_DATA_SPECIFIED 0x00000001 /* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10. - * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the + * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the * CKM_RSA_PKCS_OAEP mechanism. */ typedef struct CK_RSA_PKCS_OAEP_PARAMS { - CK_MECHANISM_TYPE hashAlg; - CK_RSA_PKCS_OAEP_MGF_TYPE mgf; - CK_RSA_PKCS_OAEP_SOURCE_TYPE source; - CK_VOID_PTR pSourceData; - CK_ULONG ulSourceDataLen; + CK_MECHANISM_TYPE hashAlg; + CK_RSA_PKCS_MGF_TYPE mgf; + CK_RSA_PKCS_OAEP_SOURCE_TYPE source; + CK_VOID_PTR pSourceData; + CK_ULONG ulSourceDataLen; } CK_RSA_PKCS_OAEP_PARAMS; typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR; +/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11. + * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the + * CKM_RSA_PKCS_PSS mechanism(s). */ +typedef struct CK_RSA_PKCS_PSS_PARAMS { + CK_MECHANISM_TYPE hashAlg; + CK_RSA_PKCS_MGF_TYPE mgf; + CK_ULONG sLen; +} CK_RSA_PKCS_PSS_PARAMS; + +typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR; + +/* CK_EC_KDF_TYPE is new for v2.11. */ +typedef CK_ULONG CK_EC_KDF_TYPE; + +/* The following EC Key Derivation Functions are defined */ +#define CKD_NULL 0x00000001 +#define CKD_SHA1_KDF 0x00000002 + +/* CK_ECDH1_DERIVE_PARAMS is new for v2.11. + * CK_ECDH1_DERIVE_PARAMS provides the parameters to the + * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms, + * where each party contributes one key pair. + */ +typedef struct CK_ECDH1_DERIVE_PARAMS { + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; +} CK_ECDH1_DERIVE_PARAMS; + +typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR; + + +/* CK_ECDH2_DERIVE_PARAMS is new for v2.11. + * CK_ECDH2_DERIVE_PARAMS provides the parameters to the + * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */ +typedef struct CK_ECDH2_DERIVE_PARAMS { + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; +} CK_ECDH2_DERIVE_PARAMS; + +typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR; + +typedef struct CK_ECMQV_DERIVE_PARAMS { + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; + CK_OBJECT_HANDLE publicKey; +} CK_ECMQV_DERIVE_PARAMS; + +typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR; + +/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the + * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */ +typedef CK_ULONG CK_X9_42_DH_KDF_TYPE; +typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR; + +/* The following X9.42 DH key derivation functions are defined + (besides CKD_NULL already defined : */ +#define CKD_SHA1_KDF_ASN1 0x00000003 +#define CKD_SHA1_KDF_CONCATENATE 0x00000004 + +/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11. + * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the + * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party + * contributes one key pair */ +typedef struct CK_X9_42_DH1_DERIVE_PARAMS { + CK_X9_42_DH_KDF_TYPE kdf; + CK_ULONG ulOtherInfoLen; + CK_BYTE_PTR pOtherInfo; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; +} CK_X9_42_DH1_DERIVE_PARAMS; + +typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR; + +/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11. + * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the + * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation + * mechanisms, where each party contributes two key pairs */ +typedef struct CK_X9_42_DH2_DERIVE_PARAMS { + CK_X9_42_DH_KDF_TYPE kdf; + CK_ULONG ulOtherInfoLen; + CK_BYTE_PTR pOtherInfo; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; +} CK_X9_42_DH2_DERIVE_PARAMS; + +typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR; + +typedef struct CK_X9_42_MQV_DERIVE_PARAMS { + CK_X9_42_DH_KDF_TYPE kdf; + CK_ULONG ulOtherInfoLen; + CK_BYTE_PTR pOtherInfo; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; + CK_ULONG ulPrivateDataLen; + CK_OBJECT_HANDLE hPrivateData; + CK_ULONG ulPublicDataLen2; + CK_BYTE_PTR pPublicData2; + CK_OBJECT_HANDLE publicKey; +} CK_X9_42_MQV_DERIVE_PARAMS; + +typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR; + /* CK_KEA_DERIVE_PARAMS provides the parameters to the * CKM_KEA_DERIVE mechanism */ /* CK_KEA_DERIVE_PARAMS is new for v2.0 */ @@ -1213,6 +1463,22 @@ typedef CK_ULONG CK_MAC_GENERAL_PARAMS; typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR; +/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */ +typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[8]; + CK_BYTE_PTR pData; + CK_ULONG length; +} CK_DES_CBC_ENCRYPT_DATA_PARAMS; + +typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR; + +typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS { + CK_BYTE iv[16]; + CK_BYTE_PTR pData; + CK_ULONG length; +} CK_AES_CBC_ENCRYPT_DATA_PARAMS; + +typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR; /* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the * CKM_SKIPJACK_PRIVATE_WRAP mechanism */ @@ -1260,12 +1526,12 @@ typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \ typedef struct CK_PBE_PARAMS { - CK_CHAR_PTR pInitVector; - CK_CHAR_PTR pPassword; - CK_ULONG ulPasswordLen; - CK_CHAR_PTR pSalt; - CK_ULONG ulSaltLen; - CK_ULONG ulIteration; + CK_BYTE_PTR pInitVector; + CK_UTF8CHAR_PTR pPassword; + CK_ULONG ulPasswordLen; + CK_BYTE_PTR pSalt; + CK_ULONG ulSaltLen; + CK_ULONG ulIteration; } CK_PBE_PARAMS; typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR; @@ -1324,6 +1590,83 @@ typedef struct CK_SSL3_KEY_MAT_PARAMS { typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR; +/* CK_TLS_PRF_PARAMS is new for version 2.20 */ +typedef struct CK_TLS_PRF_PARAMS { + CK_BYTE_PTR pSeed; + CK_ULONG ulSeedLen; + CK_BYTE_PTR pLabel; + CK_ULONG ulLabelLen; + CK_BYTE_PTR pOutput; + CK_ULONG_PTR pulOutputLen; +} CK_TLS_PRF_PARAMS; + +typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR; + +/* WTLS is new for version 2.20 */ +typedef struct CK_WTLS_RANDOM_DATA { + CK_BYTE_PTR pClientRandom; + CK_ULONG ulClientRandomLen; + CK_BYTE_PTR pServerRandom; + CK_ULONG ulServerRandomLen; +} CK_WTLS_RANDOM_DATA; + +typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR; + +typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS { + CK_MECHANISM_TYPE DigestMechanism; + CK_WTLS_RANDOM_DATA RandomInfo; + CK_BYTE_PTR pVersion; +} CK_WTLS_MASTER_KEY_DERIVE_PARAMS; + +typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \ + CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR; + +typedef struct CK_WTLS_PRF_PARAMS { + CK_MECHANISM_TYPE DigestMechanism; + CK_BYTE_PTR pSeed; + CK_ULONG ulSeedLen; + CK_BYTE_PTR pLabel; + CK_ULONG ulLabelLen; + CK_BYTE_PTR pOutput; + CK_ULONG_PTR pulOutputLen; +} CK_WTLS_PRF_PARAMS; + +typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR; + +typedef struct CK_WTLS_KEY_MAT_OUT { + CK_OBJECT_HANDLE hMacSecret; + CK_OBJECT_HANDLE hKey; + CK_BYTE_PTR pIV; +} CK_WTLS_KEY_MAT_OUT; + +typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR; + +typedef struct CK_WTLS_KEY_MAT_PARAMS { + CK_MECHANISM_TYPE DigestMechanism; + CK_ULONG ulMacSizeInBits; + CK_ULONG ulKeySizeInBits; + CK_ULONG ulIVSizeInBits; + CK_ULONG ulSequenceNumber; + CK_BBOOL bIsExport; + CK_WTLS_RANDOM_DATA RandomInfo; + CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial; +} CK_WTLS_KEY_MAT_PARAMS; + +typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR; + +/* CMS is new for version 2.20 */ +typedef struct CK_CMS_SIG_PARAMS { + CK_OBJECT_HANDLE certificateHandle; + CK_MECHANISM_PTR pSigningMechanism; + CK_MECHANISM_PTR pDigestMechanism; + CK_UTF8CHAR_PTR pContentType; + CK_BYTE_PTR pRequestedAttributes; + CK_ULONG ulRequestedAttributesLen; + CK_BYTE_PTR pRequiredAttributes; + CK_ULONG ulRequiredAttributesLen; +} CK_CMS_SIG_PARAMS; + +typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR; typedef struct CK_KEY_DERIVATION_STRING_DATA { CK_BYTE_PTR pData; @@ -1344,8 +1687,8 @@ typedef CK_ULONG CK_EXTRACT_PARAMS; typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR; /* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10. - * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to - * indicate the Pseudo-Random Function (PRF) used to generate + * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to + * indicate the Pseudo-Random Function (PRF) used to generate * key bits using PKCS #5 PBKDF2. */ typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE; @@ -1355,9 +1698,9 @@ typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_ #define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001 -/* CK_PKCS5_PBKD2_SALT_SOURCE_TYPE is new for v2.10. - * CK_PKCS5_PBKD2_SALT_SOURCE_TYPE is used to indicate the - * source of the salt value when deriving a key using PKCS #5 +/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10. + * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the + * source of the salt value when deriving a key using PKCS #5 * PBKDF2. */ typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE; @@ -1367,40 +1710,35 @@ typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE #define CKZ_SALT_SPECIFIED 0x00000001 /* CK_PKCS5_PBKD2_PARAMS is new for v2.10. - * CK_PKCS5_PBKD2_PARAMS is a structure that provides the + * CK_PKCS5_PBKD2_PARAMS is a structure that provides the * parameters to the CKM_PKCS5_PBKD2 mechanism. */ typedef struct CK_PKCS5_PBKD2_PARAMS { - CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource; - CK_VOID_PTR pSaltSourceData; - CK_ULONG ulSaltSourceDataLen; - CK_ULONG iterations; - CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf; - CK_VOID_PTR pPrfData; - CK_ULONG ulPrfDataLen; + CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource; + CK_VOID_PTR pSaltSourceData; + CK_ULONG ulSaltSourceDataLen; + CK_ULONG iterations; + CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf; + CK_VOID_PTR pPrfData; + CK_ULONG ulPrfDataLen; + CK_UTF8CHAR_PTR pPassword; + CK_ULONG_PTR ulPasswordLen; } CK_PKCS5_PBKD2_PARAMS; - + typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR; -/* CK_ECDH1_DERIVE_PARAMS is defined in Section 12.4.4 of - * PKCS#11v2.11. This structure provides parameters for - * the CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE key - * derivation mechanisms. - */ -typedef CK_ULONG CK_EC_KDF_TYPE; -#define CKD_NULL 0x00000001 -#define CKD_SHA1_KDF 0x00000002 - -typedef struct CK_ECDH1_DERIVE_PARAMS { - CK_EC_KDF_TYPE kdf; - CK_ULONG ulSharedDataLen; - CK_BYTE_PTR pSharedData; - CK_ULONG ulPublicDataLen; - CK_BYTE_PTR pPublicData; -} CK_ECDH1_DERIVE_PARAMS; +/* NSS Specific defines */ -typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR; +/* defines that have been deprecated in 2.20, but maintained in our + * header file for backward compatibility */ +#define CKO_KG_PARAMETERS CKO_DOMAIN_PARAMETERS +#define CKF_EC_FP CKF_EC_F_P +/* new in v2.11 deprecated by 2.20 */ +#define CKR_KEY_PARAMS_INVALID 0x0000006B + +/* stuff that for historic reasons is in this header file but should have + * been in pkcs11n.h */ +#define CKK_INVALID_KEY_TYPE 0xffffffff -/* Netscape Specific defines */ #include "pkcs11n.h" /* undo packing */ diff --git a/security/nss/lib/softoken/pkcs11u.c b/security/nss/lib/softoken/pkcs11u.c index 8555f2bf3..8e68587ce 100644 --- a/security/nss/lib/softoken/pkcs11u.c +++ b/security/nss/lib/softoken/pkcs11u.c @@ -193,6 +193,10 @@ sftk_FreeAttribute(SFTKAttribute *attribute) #define SFTK_DEF_ATTRIBUTE(value,len) \ { NULL, NULL, PR_FALSE, PR_FALSE, 0, { 0, value, len } } +#define SFTK_CLONE_ATTR(type, staticAttr) \ + sftk_NewTokenAttribute( type, staticAttr.attrib.pValue, \ + staticAttr.attrib.ulValueLen, PR_FALSE) + CK_BBOOL sftk_staticTrueValue = CK_TRUE; CK_BBOOL sftk_staticFalseValue = CK_FALSE; static const SFTKAttribute sftk_StaticTrueAttr = @@ -236,10 +240,51 @@ static const SFTKAttribute sftk_StaticMustVerifyAttr = SFTK_DEF_ATTRIBUTE(&sftk_staticMustVerifyValue, sizeof(sftk_staticMustVerifyValue)); +/* + * helper functions which get the database and call the underlying + * low level database function. + */ +static char * +sftk_FindKeyNicknameByPublicKey(SFTKSlot *slot, SECItem *dbKey) +{ + NSSLOWKEYDBHandle *keyHandle; + char * label; + + keyHandle = sftk_getKeyDB(slot); + if (!keyHandle) { + return NULL; + } + + label = nsslowkey_FindKeyNicknameByPublicKey(keyHandle, dbKey, + slot->password); + sftk_freeKeyDB(keyHandle); + return label; +} + + +NSSLOWKEYPrivateKey * +sftk_FindKeyByPublicKey(SFTKSlot *slot, SECItem *dbKey) +{ + NSSLOWKEYPrivateKey *privKey; + NSSLOWKEYDBHandle *keyHandle; + + keyHandle = sftk_getKeyDB(slot); + if (keyHandle == NULL) { + return NULL; + } + privKey = nsslowkey_FindKeyByPublicKey(keyHandle, dbKey, slot->password); + sftk_freeKeyDB(keyHandle); + if (privKey == NULL) { + return NULL; + } + return privKey; +} + static certDBEntrySMime * sftk_getSMime(SFTKTokenObject *object) { certDBEntrySMime *entry; + NSSLOWCERTCertDBHandle *certHandle; if (object->obj.objclass != CKO_NETSCAPE_SMIME) { return NULL; @@ -248,10 +293,14 @@ sftk_getSMime(SFTKTokenObject *object) return (certDBEntrySMime *)object->obj.objectInfo; } - entry = nsslowcert_ReadDBSMimeEntry(object->obj.slot->certDB, - (char *)object->dbKey.data); + certHandle = sftk_getCertDB(object->obj.slot); + if (!certHandle) { + return NULL; + } + entry = nsslowcert_ReadDBSMimeEntry(certHandle, (char *)object->dbKey.data); object->obj.objectInfo = (void *)entry; object->obj.infoFree = (SFTKFree) nsslowcert_DestroyDBEntry; + sftk_freeCertDB(certHandle); return entry; } @@ -260,6 +309,7 @@ sftk_getCrl(SFTKTokenObject *object) { certDBEntryRevocation *crl; PRBool isKrl; + NSSLOWCERTCertDBHandle *certHandle; if (object->obj.objclass != CKO_NETSCAPE_CRL) { return NULL; @@ -269,15 +319,20 @@ sftk_getCrl(SFTKTokenObject *object) } isKrl = (PRBool) (object->obj.handle == SFTK_TOKEN_KRL_HANDLE); - crl = nsslowcert_FindCrlByKey(object->obj.slot->certDB, - &object->dbKey, isKrl); + certHandle = sftk_getCertDB(object->obj.slot); + if (!certHandle) { + return NULL; + } + + crl = nsslowcert_FindCrlByKey(certHandle, &object->dbKey, isKrl); object->obj.objectInfo = (void *)crl; object->obj.infoFree = (SFTKFree) nsslowcert_DestroyDBEntry; + sftk_freeCertDB(certHandle); return crl; } static NSSLOWCERTCertificate * -sftk_getCert(SFTKTokenObject *object) +sftk_getCert(SFTKTokenObject *object, NSSLOWCERTCertDBHandle *certHandle) { NSSLOWCERTCertificate *cert; CK_OBJECT_CLASS objClass = object->obj.objclass; @@ -288,7 +343,7 @@ sftk_getCert(SFTKTokenObject *object) if (objClass == CKO_CERTIFICATE && object->obj.objectInfo) { return (NSSLOWCERTCertificate *)object->obj.objectInfo; } - cert = nsslowcert_FindCertByKey(object->obj.slot->certDB,&object->dbKey); + cert = nsslowcert_FindCertByKey(certHandle, &object->dbKey); if (objClass == CKO_CERTIFICATE) { object->obj.objectInfo = (void *)cert; object->obj.infoFree = (SFTKFree) nsslowcert_DestroyCertificate ; @@ -300,6 +355,7 @@ static NSSLOWCERTTrust * sftk_getTrust(SFTKTokenObject *object) { NSSLOWCERTTrust *trust; + NSSLOWCERTCertDBHandle *certHandle; if (object->obj.objclass != CKO_NETSCAPE_TRUST) { return NULL; @@ -307,9 +363,14 @@ sftk_getTrust(SFTKTokenObject *object) if (object->obj.objectInfo) { return (NSSLOWCERTTrust *)object->obj.objectInfo; } - trust = nsslowcert_FindTrustByKey(object->obj.slot->certDB,&object->dbKey); + certHandle = sftk_getCertDB(object->obj.slot); + if (!certHandle) { + return NULL; + } + trust = nsslowcert_FindTrustByKey(certHandle, &object->dbKey); object->obj.objectInfo = (void *)trust; object->obj.infoFree = (SFTKFree) nsslowcert_DestroyTrust ; + sftk_freeCertDB(certHandle); return trust; } @@ -325,8 +386,7 @@ sftk_GetPublicKey(SFTKTokenObject *object) if (object->obj.objectInfo) { return (NSSLOWKEYPublicKey *)object->obj.objectInfo; } - privKey = nsslowkey_FindKeyByPublicKey(object->obj.slot->keyDB, - &object->dbKey, object->obj.slot->password); + privKey = sftk_FindKeyByPublicKey(object->obj.slot, &object->dbKey); if (privKey == NULL) { return NULL; } @@ -337,8 +397,16 @@ sftk_GetPublicKey(SFTKTokenObject *object) return pubKey; } +/* + * we need two versions of sftk_GetPrivateKey. One version that takes the + * DB handle so we can pass the handle we have already acquired in, + * rather than going through the 'getKeyDB' code again, + * which may fail the second time and another which just aquires + * the key handle from the slot (where we don't already have a key handle. + * This version does the former. + */ static NSSLOWKEYPrivateKey * -sftk_GetPrivateKey(SFTKTokenObject *object) +sftk_GetPrivateKeyWithDB(SFTKTokenObject *object, NSSLOWKEYDBHandle *keyHandle) { NSSLOWKEYPrivateKey *privKey; @@ -349,8 +417,8 @@ sftk_GetPrivateKey(SFTKTokenObject *object) if (object->obj.objectInfo) { return (NSSLOWKEYPrivateKey *)object->obj.objectInfo; } - privKey = nsslowkey_FindKeyByPublicKey(object->obj.slot->keyDB, - &object->dbKey, object->obj.slot->password); + privKey = nsslowkey_FindKeyByPublicKey(keyHandle, &object->dbKey, + object->obj.slot->password); if (privKey == NULL) { return NULL; } @@ -359,6 +427,22 @@ sftk_GetPrivateKey(SFTKTokenObject *object) return privKey; } +/* this version does the latter */ +static NSSLOWKEYPrivateKey * +sftk_GetPrivateKey(SFTKTokenObject *object) +{ + NSSLOWKEYDBHandle *keyHandle; + NSSLOWKEYPrivateKey *privKey; + + keyHandle = sftk_getKeyDB(object->obj.slot); + if (!keyHandle) { + return NULL; + } + privKey = sftk_GetPrivateKeyWithDB(object, keyHandle); + sftk_freeKeyDB(keyHandle); + return privKey; +} + /* sftk_GetPubItem returns data associated with the public key. * one only needs to free the public key. This comment is here * because this sematic would be non-obvious otherwise. All callers @@ -407,12 +491,12 @@ sftk_FindRSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len); return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); case CKA_DERIVE: - return (SFTKAttribute *) &sftk_StaticFalseAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr); case CKA_ENCRYPT: case CKA_VERIFY: case CKA_VERIFY_RECOVER: case CKA_WRAP: - return (SFTKAttribute *) &sftk_StaticTrueAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr); case CKA_MODULUS: return sftk_NewTokenAttributeSigned(type,key->u.rsa.modulus.data, key->u.rsa.modulus.len, PR_FALSE); @@ -442,9 +526,9 @@ sftk_FindDSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) case CKA_ENCRYPT: case CKA_VERIFY_RECOVER: case CKA_WRAP: - return (SFTKAttribute *) &sftk_StaticFalseAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr); case CKA_VERIFY: - return (SFTKAttribute *) &sftk_StaticTrueAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr); case CKA_VALUE: return sftk_NewTokenAttributeSigned(type,key->u.dsa.publicValue.data, key->u.dsa.publicValue.len, PR_FALSE); @@ -477,12 +561,12 @@ sftk_FindDHPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len); return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); case CKA_DERIVE: - return (SFTKAttribute *) &sftk_StaticTrueAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr); case CKA_ENCRYPT: case CKA_VERIFY: case CKA_VERIFY_RECOVER: case CKA_WRAP: - return (SFTKAttribute *) &sftk_StaticFalseAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr); case CKA_VALUE: return sftk_NewTokenAttributeSigned(type,key->u.dh.publicValue.data, key->u.dh.publicValue.len, PR_FALSE); @@ -514,11 +598,11 @@ sftk_FindECPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); case CKA_DERIVE: case CKA_VERIFY: - return (SFTKAttribute *) &sftk_StaticTrueAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr); case CKA_ENCRYPT: case CKA_VERIFY_RECOVER: case CKA_WRAP: - return (SFTKAttribute *) &sftk_StaticFalseAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr); case CKA_EC_PARAMS: /* XXX Why is the last arg PR_FALSE? */ return sftk_NewTokenAttributeSigned(type, @@ -536,10 +620,11 @@ sftk_FindECPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) } #endif /* NSS_ENABLE_ECC */ + static SFTKAttribute * sftk_FindPublicKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) { - NSSLOWKEYPublicKey *key; + NSSLOWKEYPublicKey *key; SFTKAttribute *att = NULL; char *label; @@ -548,15 +633,15 @@ sftk_FindPublicKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) case CKA_SENSITIVE: case CKA_ALWAYS_SENSITIVE: case CKA_NEVER_EXTRACTABLE: - return (SFTKAttribute *) &sftk_StaticFalseAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr); case CKA_MODIFIABLE: case CKA_EXTRACTABLE: - return (SFTKAttribute *) &sftk_StaticTrueAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr); case CKA_LABEL: - label = nsslowkey_FindKeyNicknameByPublicKey(object->obj.slot->keyDB, - &object->dbKey, object->obj.slot->password); + label = sftk_FindKeyNicknameByPublicKey(object->obj.slot, + &object->dbKey); if (label == NULL) { - return (SFTKAttribute *)&sftk_StaticOneAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticOneAttr); } att = sftk_NewTokenAttribute(type,label,PORT_Strlen(label), PR_TRUE); PORT_Free(label); @@ -591,7 +676,7 @@ sftk_FindPublicKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) static SFTKAttribute * sftk_FindSecretKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) { - NSSLOWKEYPrivateKey *key; + NSSLOWKEYPrivateKey *key; char *label; unsigned char *keyString; SFTKAttribute *att; @@ -613,14 +698,14 @@ sftk_FindSecretKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) case CKA_WRAP: case CKA_UNWRAP: case CKA_MODIFIABLE: - return (SFTKAttribute *) &sftk_StaticTrueAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr); case CKA_NEVER_EXTRACTABLE: - return (SFTKAttribute *) &sftk_StaticFalseAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr); case CKA_LABEL: - label = nsslowkey_FindKeyNicknameByPublicKey(object->obj.slot->keyDB, - &object->dbKey, object->obj.slot->password); + label = sftk_FindKeyNicknameByPublicKey(object->obj.slot, + &object->dbKey); if (label == NULL) { - return (SFTKAttribute *)&sftk_StaticNullAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr); } att = sftk_NewTokenAttribute(type,label,PORT_Strlen(label), PR_TRUE); PORT_Free(label); @@ -723,7 +808,7 @@ sftk_FindSecretKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) static SFTKAttribute * sftk_FindRSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, - CK_ATTRIBUTE_TYPE type) + CK_ATTRIBUTE_TYPE type) { unsigned char hash[SHA1_LENGTH]; CK_KEY_TYPE keyType = CKK_RSA; @@ -735,12 +820,12 @@ sftk_FindRSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len); return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); case CKA_DERIVE: - return (SFTKAttribute *) &sftk_StaticFalseAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr); case CKA_DECRYPT: case CKA_SIGN: case CKA_SIGN_RECOVER: case CKA_UNWRAP: - return (SFTKAttribute *) &sftk_StaticTrueAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr); case CKA_MODULUS: return sftk_NewTokenAttributeSigned(type,key->u.rsa.modulus.data, key->u.rsa.modulus.len, PR_FALSE); @@ -748,12 +833,24 @@ sftk_FindRSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, return sftk_NewTokenAttributeSigned(type,key->u.rsa.publicExponent.data, key->u.rsa.publicExponent.len, PR_FALSE); case CKA_PRIVATE_EXPONENT: + return sftk_NewTokenAttributeSigned(type, + key->u.rsa.privateExponent.data, + key->u.rsa.privateExponent.len, PR_FALSE); case CKA_PRIME_1: + return sftk_NewTokenAttributeSigned(type, key->u.rsa.prime1.data, + key->u.rsa.prime1.len, PR_FALSE); case CKA_PRIME_2: + return sftk_NewTokenAttributeSigned(type, key->u.rsa.prime2.data, + key->u.rsa.prime2.len, PR_FALSE); case CKA_EXPONENT_1: + return sftk_NewTokenAttributeSigned(type, key->u.rsa.exponent1.data, + key->u.rsa.exponent1.len, PR_FALSE); case CKA_EXPONENT_2: + return sftk_NewTokenAttributeSigned(type, key->u.rsa.exponent2.data, + key->u.rsa.exponent2.len, PR_FALSE); case CKA_COEFFICIENT: - return (SFTKAttribute *) &sftk_StaticNullAttr; + return sftk_NewTokenAttributeSigned(type, key->u.rsa.coefficient.data, + key->u.rsa.coefficient.len, PR_FALSE); default: break; } @@ -772,17 +869,18 @@ sftk_FindDSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, return sftk_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE); case CKA_ID: SHA1_HashBuf(hash,key->u.dsa.publicValue.data, - key->u.dsa.publicValue.len); + key->u.dsa.publicValue.len); return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); case CKA_DERIVE: case CKA_DECRYPT: case CKA_SIGN_RECOVER: case CKA_UNWRAP: - return (SFTKAttribute *) &sftk_StaticFalseAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr); case CKA_SIGN: - return (SFTKAttribute *) &sftk_StaticTrueAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr); case CKA_VALUE: - return (SFTKAttribute *) &sftk_StaticNullAttr; + return sftk_NewTokenAttributeSigned(type, key->u.dsa.privateValue.data, + key->u.dsa.privateValue.len, PR_FALSE); case CKA_PRIME: return sftk_NewTokenAttributeSigned(type,key->u.dsa.params.prime.data, key->u.dsa.params.prime.len, PR_FALSE); @@ -812,14 +910,15 @@ sftk_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type) SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len); return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); case CKA_DERIVE: - return (SFTKAttribute *) &sftk_StaticTrueAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr); case CKA_DECRYPT: case CKA_SIGN: case CKA_SIGN_RECOVER: case CKA_UNWRAP: - return (SFTKAttribute *) &sftk_StaticFalseAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr); case CKA_VALUE: - return (SFTKAttribute *) &sftk_StaticNullAttr; + return sftk_NewTokenAttributeSigned(type,key->u.dh.privateValue.data, + key->u.dh.privateValue.len, PR_FALSE); case CKA_PRIME: return sftk_NewTokenAttributeSigned(type,key->u.dh.prime.data, key->u.dh.prime.len, PR_FALSE); @@ -847,13 +946,14 @@ sftk_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type) return sftk_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); case CKA_DERIVE: case CKA_SIGN: - return (SFTKAttribute *) &sftk_StaticTrueAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr); case CKA_DECRYPT: case CKA_SIGN_RECOVER: case CKA_UNWRAP: - return (SFTKAttribute *) &sftk_StaticFalseAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr); case CKA_VALUE: - return (SFTKAttribute *) &sftk_StaticNullAttr; + return sftk_NewTokenAttributeSigned(type, key->u.ec.privateValue.data, + key->u.ec.privateValue.len, PR_FALSE); case CKA_EC_PARAMS: /* XXX Why is the last arg PR_FALSE? */ return sftk_NewTokenAttributeSigned(type, @@ -870,7 +970,7 @@ sftk_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type) static SFTKAttribute * sftk_FindPrivateKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) { - NSSLOWKEYPrivateKey *key; + NSSLOWKEYPrivateKey *key; char *label; SFTKAttribute *att; @@ -880,16 +980,16 @@ sftk_FindPrivateKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) case CKA_ALWAYS_SENSITIVE: case CKA_EXTRACTABLE: case CKA_MODIFIABLE: - return (SFTKAttribute *) &sftk_StaticTrueAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr); case CKA_NEVER_EXTRACTABLE: - return (SFTKAttribute *) &sftk_StaticFalseAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr); case CKA_SUBJECT: - return (SFTKAttribute *)&sftk_StaticNullAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr); case CKA_LABEL: - label = nsslowkey_FindKeyNicknameByPublicKey(object->obj.slot->keyDB, - &object->dbKey, object->obj.slot->password); + label = sftk_FindKeyNicknameByPublicKey(object->obj.slot, + &object->dbKey); if (label == NULL) { - return (SFTKAttribute *)&sftk_StaticNullAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr); } att = sftk_NewTokenAttribute(type,label,PORT_Strlen(label), PR_TRUE); PORT_Free(label); @@ -926,7 +1026,7 @@ sftk_FindSMIMEAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) switch (type) { case CKA_PRIVATE: case CKA_MODIFIABLE: - return (SFTKAttribute *) &sftk_StaticFalseAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr); case CKA_NETSCAPE_EMAIL: return sftk_NewTokenAttribute(type,object->dbKey.data, object->dbKey.len-1, PR_FALSE); @@ -966,9 +1066,9 @@ sftk_FindTrustAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) switch (type) { case CKA_PRIVATE: - return (SFTKAttribute *) &sftk_StaticFalseAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr); case CKA_MODIFIABLE: - return (SFTKAttribute *) &sftk_StaticTrueAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr); case CKA_CERT_SHA1_HASH: case CKA_CERT_MD5_HASH: case CKA_TRUST_CLIENT_AUTH: @@ -1005,29 +1105,29 @@ sftk_FindTrustAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) trustFlags = trust->trust->objectSigningFlags; trust: if (trustFlags & CERTDB_TRUSTED_CA ) { - return (SFTKAttribute *)&sftk_StaticTrustedDelegatorAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticTrustedDelegatorAttr); } if (trustFlags & CERTDB_TRUSTED) { - return (SFTKAttribute *)&sftk_StaticTrustedAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticTrustedAttr); } if (trustFlags & CERTDB_NOT_TRUSTED) { - return (SFTKAttribute *)&sftk_StaticUnTrustedAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticUnTrustedAttr); } if (trustFlags & CERTDB_TRUSTED_UNKNOWN) { - return (SFTKAttribute *)&sftk_StaticTrustUnknownAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticTrustUnknownAttr); } if (trustFlags & CERTDB_VALID_CA) { - return (SFTKAttribute *)&sftk_StaticValidDelegatorAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticValidDelegatorAttr); } if (trustFlags & CERTDB_VALID_PEER) { - return (SFTKAttribute *)&sftk_StaticValidPeerAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticValidPeerAttr); } - return (SFTKAttribute *)&sftk_StaticMustVerifyAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticMustVerifyAttr); case CKA_TRUST_STEP_UP_APPROVED: if (trust->trust->sslFlags & CERTDB_GOVT_APPROVED_CA) { - return (SFTKAttribute *)&sftk_StaticTrueAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr); } else { - return (SFTKAttribute *)&sftk_StaticFalseAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr); } default: break; @@ -1065,10 +1165,11 @@ sftk_FindCrlAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) switch (type) { case CKA_PRIVATE: case CKA_MODIFIABLE: - return (SFTKAttribute *) &sftk_StaticFalseAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr); case CKA_NETSCAPE_KRL: - return (SFTKAttribute *) ((object->obj.handle == SFTK_TOKEN_KRL_HANDLE) - ? &sftk_StaticTrueAttr : &sftk_StaticFalseAttr); + return ((object->obj.handle == SFTK_TOKEN_KRL_HANDLE) + ? SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr) + : SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr)); case CKA_SUBJECT: return sftk_NewTokenAttribute(type,object->dbKey.data, object->dbKey.len, PR_FALSE); @@ -1086,7 +1187,7 @@ sftk_FindCrlAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) switch (type) { case CKA_NETSCAPE_URL: if (crl->url == NULL) { - return (SFTKAttribute *) &sftk_StaticNullAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr); } return sftk_NewTokenAttribute(type, crl->url, PORT_Strlen(crl->url)+1, PR_TRUE); @@ -1102,19 +1203,20 @@ sftk_FindCrlAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) static SFTKAttribute * sftk_FindCertAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) { - NSSLOWCERTCertificate *cert; - NSSLOWKEYPublicKey *pubKey; + NSSLOWCERTCertificate *cert; + NSSLOWCERTCertDBHandle *certHandle; + NSSLOWKEYPublicKey *pubKey; unsigned char hash[SHA1_LENGTH]; SECItem *item; switch (type) { case CKA_PRIVATE: - return (SFTKAttribute *) &sftk_StaticFalseAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr); case CKA_MODIFIABLE: - return (SFTKAttribute *) &sftk_StaticTrueAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr); case CKA_CERTIFICATE_TYPE: /* hardcoding X.509 into here */ - return (SFTKAttribute *)&sftk_StaticX509Attr; + return SFTK_CLONE_ATTR(type,sftk_StaticX509Attr); case CKA_VALUE: case CKA_ID: case CKA_LABEL: @@ -1126,7 +1228,14 @@ sftk_FindCertAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) default: return NULL; } - cert = sftk_getCert(object); + + certHandle = sftk_getCertDB(object->obj.slot); + if (certHandle == NULL) { + return NULL; + } + + cert = sftk_getCert(object, certHandle); + sftk_freeCertDB(certHandle); if (cert == NULL) { return NULL; } @@ -1138,7 +1247,7 @@ sftk_FindCertAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) if (((cert->trust->sslFlags & CERTDB_USER) == 0) && ((cert->trust->emailFlags & CERTDB_USER) == 0) && ((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) { - return (SFTKAttribute *) &sftk_StaticNullAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr); } pubKey = nsslowcert_ExtractPublicKey(cert); if (pubKey == NULL) break; @@ -1152,9 +1261,10 @@ sftk_FindCertAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) nsslowkey_DestroyPublicKey(pubKey); return sftk_NewTokenAttribute(type, hash, SHA1_LENGTH, PR_TRUE); case CKA_LABEL: - return cert->nickname ? sftk_NewTokenAttribute(type, cert->nickname, - PORT_Strlen(cert->nickname), PR_FALSE) : - (SFTKAttribute *) &sftk_StaticNullAttr; + return cert->nickname + ? sftk_NewTokenAttribute(type, cert->nickname, + PORT_Strlen(cert->nickname), PR_FALSE) + : SFTK_CLONE_ATTR(type,sftk_StaticNullAttr); case CKA_SUBJECT: return sftk_NewTokenAttribute(type,cert->derSubject.data, cert->derSubject.len, PR_FALSE); @@ -1168,7 +1278,7 @@ sftk_FindCertAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) return (cert->emailAddr && cert->emailAddr[0]) ? sftk_NewTokenAttribute(type, cert->emailAddr, PORT_Strlen(cert->emailAddr), PR_FALSE) - : (SFTKAttribute *) &sftk_StaticNullAttr; + : SFTK_CLONE_ATTR(type,sftk_StaticNullAttr); default: break; } @@ -1184,7 +1294,7 @@ sftk_FindTokenAttribute(SFTKTokenObject *object,CK_ATTRIBUTE_TYPE type) return sftk_NewTokenAttribute(type,&object->obj.objclass, sizeof(object->obj.objclass),PR_FALSE); case CKA_TOKEN: - return (SFTKAttribute *) &sftk_StaticTrueAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr); case CKA_LABEL: if ( (object->obj.objclass == CKO_CERTIFICATE) || (object->obj.objclass == CKO_PRIVATE_KEY) @@ -1192,7 +1302,7 @@ sftk_FindTokenAttribute(SFTKTokenObject *object,CK_ATTRIBUTE_TYPE type) || (object->obj.objclass == CKO_SECRET_KEY)) { break; } - return (SFTKAttribute *) &sftk_StaticNullAttr; + return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr); default: break; } @@ -1247,7 +1357,8 @@ unsigned int sftk_GetLengthInBits(unsigned char *buf, unsigned int bufLen) { unsigned int size = bufLen * 8; - int i; + unsigned int i; + /* Get the real length in bytes */ for (i=0; i < bufLen; i++) { unsigned char c = *buf++; @@ -1279,7 +1390,7 @@ sftk_ConstrainAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type, int minLength, int maxLength, int minMultiple) { SFTKAttribute *attribute; - unsigned int size; + int size; unsigned char *ptr; attribute = sftk_FindAttribute(object, type); @@ -1441,9 +1552,11 @@ static CK_RV sftk_SetCertAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type, void *value, unsigned int len) { - NSSLOWCERTCertificate *cert; + NSSLOWCERTCertificate *cert; + NSSLOWCERTCertDBHandle *certHandle; char *nickname = NULL; SECStatus rv; + CK_RV crv; /* we can't change the EMAIL values, but let the * upper layers feel better about the fact we tried to set these */ @@ -1451,17 +1564,21 @@ sftk_SetCertAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type, return CKR_OK; } - if (to->obj.slot->certDB == NULL) { - return CKR_TOKEN_WRITE_PROTECTED; + certHandle = sftk_getCertDB(to->obj.slot); + if (certHandle == NULL) { + crv = CKR_TOKEN_WRITE_PROTECTED; + goto done; } if ((type != CKA_LABEL) && (type != CKA_ID)) { - return CKR_ATTRIBUTE_READ_ONLY; + crv = CKR_ATTRIBUTE_READ_ONLY; + goto done; } - cert = sftk_getCert(to); + cert = sftk_getCert(to, certHandle); if (cert == NULL) { - return CKR_OBJECT_HANDLE_INVALID; + crv = CKR_OBJECT_HANDLE_INVALID; + goto done; } /* if the app is trying to set CKA_ID, it's probably because it just @@ -1472,33 +1589,45 @@ sftk_SetCertAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type, ((cert->trust->emailFlags & CERTDB_USER) == 0) && ((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) { SFTKSlot *slot = to->obj.slot; - - if (slot->keyDB && nsslowkey_KeyForCertExists(slot->keyDB,cert)) { - NSSLOWCERTCertTrust trust = *cert->trust; - trust.sslFlags |= CERTDB_USER; - trust.emailFlags |= CERTDB_USER; - trust.objectSigningFlags |= CERTDB_USER; - nsslowcert_ChangeCertTrust(slot->certDB,cert,&trust); + NSSLOWKEYDBHandle *keyHandle; + + keyHandle = sftk_getKeyDB(slot); + if (keyHandle) { + if (nsslowkey_KeyForCertExists(keyHandle, cert)) { + NSSLOWCERTCertTrust trust = *cert->trust; + trust.sslFlags |= CERTDB_USER; + trust.emailFlags |= CERTDB_USER; + trust.objectSigningFlags |= CERTDB_USER; + nsslowcert_ChangeCertTrust(certHandle,cert,&trust); + } + sftk_freeKeyDB(keyHandle); } } - return CKR_OK; + crv = CKR_OK; + goto done; } /* must be CKA_LABEL */ if (value != NULL) { nickname = PORT_ZAlloc(len+1); if (nickname == NULL) { - return CKR_HOST_MEMORY; + crv = CKR_HOST_MEMORY; + goto done; } PORT_Memcpy(nickname,value,len); nickname[len] = 0; } - rv = nsslowcert_AddPermNickname(to->obj.slot->certDB, cert, nickname); - if (nickname) PORT_Free(nickname); - if (rv != SECSuccess) { - return CKR_DEVICE_ERROR; + rv = nsslowcert_AddPermNickname(certHandle, cert, nickname); + crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR; + +done: + if (nickname) { + PORT_Free(nickname); } - return CKR_OK; + if (certHandle) { + sftk_freeCertDB(certHandle); + } + return crv; } static CK_RV @@ -1506,8 +1635,10 @@ sftk_SetPrivateKeyAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type, void *value, unsigned int len) { NSSLOWKEYPrivateKey *privKey; + NSSLOWKEYDBHandle *keyHandle; char *nickname = NULL; SECStatus rv; + CK_RV crv; /* we can't change the ID and we don't store the subject, but let the * upper layers feel better about the fact we tried to set these */ @@ -1515,32 +1646,41 @@ sftk_SetPrivateKeyAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type, return CKR_OK; } - if (to->obj.slot->keyDB == NULL) { - return CKR_TOKEN_WRITE_PROTECTED; + keyHandle = sftk_getKeyDB(to->obj.slot); + if (keyHandle == NULL) { + crv = CKR_TOKEN_WRITE_PROTECTED; + goto done; } if (type != CKA_LABEL) { - return CKR_ATTRIBUTE_READ_ONLY; + crv = CKR_ATTRIBUTE_READ_ONLY; + goto done; } - privKey = sftk_GetPrivateKey(to); + privKey = sftk_GetPrivateKeyWithDB(to, keyHandle); if (privKey == NULL) { - return CKR_OBJECT_HANDLE_INVALID; + crv = CKR_OBJECT_HANDLE_INVALID; + goto done; } if (value != NULL) { nickname = PORT_ZAlloc(len+1); if (nickname == NULL) { - return CKR_HOST_MEMORY; + crv = CKR_HOST_MEMORY; + goto done; } PORT_Memcpy(nickname,value,len); nickname[len] = 0; } - rv = nsslowkey_UpdateNickname(to->obj.slot->keyDB, privKey, &to->dbKey, + rv = nsslowkey_UpdateNickname(keyHandle, privKey, &to->dbKey, nickname, to->obj.slot->password); - if (nickname) PORT_Free(nickname); - if (rv != SECSuccess) { - return CKR_DEVICE_ERROR; + crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR; +done: + if (nickname) { + PORT_Free(nickname); } - return CKR_OK; + if (keyHandle) { + sftk_freeKeyDB(keyHandle); + } + return crv; } static CK_RV @@ -1549,22 +1689,29 @@ sftk_SetTrustAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type, { unsigned int flags; CK_TRUST trust; - NSSLOWCERTCertificate *cert; - NSSLOWCERTCertTrust dbTrust; + NSSLOWCERTCertificate *cert; + NSSLOWCERTCertDBHandle *certHandle; + NSSLOWCERTCertTrust dbTrust; SECStatus rv; + CK_RV crv; - if (to->obj.slot->certDB == NULL) { - return CKR_TOKEN_WRITE_PROTECTED; - } if (len != sizeof (CK_TRUST)) { return CKR_ATTRIBUTE_VALUE_INVALID; } trust = *(CK_TRUST *)value; flags = sftk_MapTrust(trust, (PRBool) (type == CKA_TRUST_SERVER_AUTH)); - cert = sftk_getCert(to); + certHandle = sftk_getCertDB(to->obj.slot); + + if (certHandle == NULL) { + crv = CKR_TOKEN_WRITE_PROTECTED; + goto done; + } + + cert = sftk_getCert(to, certHandle); if (cert == NULL) { - return CKR_OBJECT_HANDLE_INVALID; + crv = CKR_OBJECT_HANDLE_INVALID; + goto done; } dbTrust = *cert->trust; @@ -1586,14 +1733,17 @@ sftk_SetTrustAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type, (CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CLIENT_CA)); break; default: - return CKR_ATTRIBUTE_READ_ONLY; + crv = CKR_ATTRIBUTE_READ_ONLY; + goto done; } - rv = nsslowcert_ChangeCertTrust(to->obj.slot->certDB,cert,&dbTrust); - if (rv != SECSuccess) { - return CKR_DEVICE_ERROR; + rv = nsslowcert_ChangeCertTrust(certHandle, cert, &dbTrust); + crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR; +done: + if (certHandle) { + sftk_freeCertDB(certHandle); } - return CKR_OK; + return crv; } static CK_RV @@ -1936,12 +2086,18 @@ sftk_deleteTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle) return rem ? SECSuccess : SECFailure; } +/* must be called holding sftk_tokenKeyLock(slot) */ static SECStatus sftk_addTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle, SECItem *key) { PLHashEntry *entry; SECItem *item; + /* don't add a new handle in the middle of closing down a slot */ + if (!slot->present) { + return SECFailure; + } + item = SECITEM_DupItem(key); if (item == NULL) { return SECFailure; @@ -1954,6 +2110,7 @@ sftk_addTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle, SECItem *key) return SECSuccess; } +/* must be called holding sftk_tokenKeyLock(slot) */ static SECItem * sftk_lookupTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle) { @@ -1975,6 +2132,25 @@ sftk_tokenKeyUnlock(SFTKSlot *slot) { PZ_Unlock(slot->objectLock); } +static PRIntn +sftk_freeHashItem(PLHashEntry* entry, PRIntn index, void *arg) +{ + SECItem *item = (SECItem *)entry->value; + + SECITEM_FreeItem(item, PR_TRUE); + return HT_ENUMERATE_NEXT; +} + +CK_RV +SFTK_ClearTokenKeyHashTable(SFTKSlot *slot) +{ + sftk_tokenKeyLock(slot); + PORT_Assert(!slot->present); + PL_HashTableEnumerateEntries(slot->tokenHashTable, sftk_freeHashItem, NULL); + sftk_tokenKeyUnlock(slot); + return CKR_OK; +} + /* allocation hooks that allow us to recycle old object structures */ static SFTKObjectFreeList sessionObjectList = { NULL, NULL, 0 }; @@ -2328,6 +2504,9 @@ sftk_DeleteObject(SFTKSession *session, SFTKObject *object) sftkqueue_clear_deleted_element(object); sftk_FreeObject(object); /* reduce it's reference count */ } else { + NSSLOWKEYDBHandle *keyHandle; + NSSLOWCERTCertDBHandle *certHandle; + PORT_Assert(to); /* remove the objects from the real data base */ switch (object->handle & SFTK_TOKEN_TYPE_MASK) { @@ -2335,30 +2514,57 @@ sftk_DeleteObject(SFTKSession *session, SFTKObject *object) case SFTK_TOKEN_TYPE_KEY: /* KEYID is the public KEY for DSA and DH, and the MODULUS for * RSA */ - PORT_Assert(slot->keyDB); - rv = nsslowkey_DeleteKey(slot->keyDB, &to->dbKey); - if (rv != SECSuccess) crv= CKR_DEVICE_ERROR; + keyHandle = sftk_getKeyDB(slot); + if (!keyHandle) { + crv = CKR_TOKEN_WRITE_PROTECTED; + break; + } + rv = nsslowkey_DeleteKey(keyHandle, &to->dbKey); + sftk_freeKeyDB(keyHandle); + if (rv != SECSuccess) { + crv = CKR_DEVICE_ERROR; + } break; case SFTK_TOKEN_TYPE_PUB: break; /* public keys only exist at the behest of the priv key */ case SFTK_TOKEN_TYPE_CERT: - cert = nsslowcert_FindCertByKey(slot->certDB,&to->dbKey); + certHandle = sftk_getCertDB(slot); + if (!certHandle) { + crv = CKR_TOKEN_WRITE_PROTECTED; + break; + } + cert = nsslowcert_FindCertByKey(certHandle,&to->dbKey); + sftk_freeCertDB(certHandle); if (cert == NULL) { crv = CKR_DEVICE_ERROR; break; } rv = nsslowcert_DeletePermCertificate(cert); - if (rv != SECSuccess) crv = CKR_DEVICE_ERROR; + if (rv != SECSuccess) { + crv = CKR_DEVICE_ERROR; + } nsslowcert_DestroyCertificate(cert); break; case SFTK_TOKEN_TYPE_CRL: + certHandle = sftk_getCertDB(slot); + if (!certHandle) { + crv = CKR_TOKEN_WRITE_PROTECTED; + break; + } isKrl = (PRBool) (object->handle == SFTK_TOKEN_KRL_HANDLE); - rv = nsslowcert_DeletePermCRL(slot->certDB,&to->dbKey,isKrl); + rv = nsslowcert_DeletePermCRL(certHandle, &to->dbKey, isKrl); + sftk_freeCertDB(certHandle); if (rv == SECFailure) crv = CKR_DEVICE_ERROR; break; case SFTK_TOKEN_TYPE_TRUST: - cert = nsslowcert_FindCertByKey(slot->certDB,&to->dbKey); + certHandle = sftk_getCertDB(slot); + if (!certHandle) { + crv = CKR_TOKEN_WRITE_PROTECTED; + break; + } + cert = nsslowcert_FindCertByKey(certHandle, &to->dbKey); if (cert == NULL) { + sftk_freeCertDB(certHandle); crv = CKR_DEVICE_ERROR; break; } @@ -2369,7 +2575,8 @@ sftk_DeleteObject(SFTKSession *session, SFTKObject *object) tmptrust.sslFlags |= CERTDB_TRUSTED_UNKNOWN; tmptrust.emailFlags |= CERTDB_TRUSTED_UNKNOWN; tmptrust.objectSigningFlags |= CERTDB_TRUSTED_UNKNOWN; - rv = nsslowcert_ChangeCertTrust(slot->certDB,cert,&tmptrust); + rv = nsslowcert_ChangeCertTrust(certHandle, cert, &tmptrust); + sftk_freeCertDB(certHandle); if (rv != SECSuccess) crv = CKR_DEVICE_ERROR; nsslowcert_DestroyCertificate(cert); break; @@ -2384,6 +2591,342 @@ sftk_DeleteObject(SFTKSession *session, SFTKObject *object) } /* + * Token objects don't explicitly store their attributes, so we need to know + * what attributes make up a particular token object before we can copy it. + * below are the tables by object type. + */ +static const CK_ATTRIBUTE_TYPE commonAttrs[] = { + CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_LABEL, CKA_MODIFIABLE +}; +static const CK_ULONG commonAttrsCount = + sizeof(commonAttrs)/sizeof(commonAttrs[0]); + +static const CK_ATTRIBUTE_TYPE commonKeyAttrs[] = { + CKA_ID, CKA_START_DATE, CKA_END_DATE, CKA_DERIVE, CKA_LOCAL, CKA_KEY_TYPE +}; +static const CK_ULONG commonKeyAttrsCount = + sizeof(commonKeyAttrs)/sizeof(commonKeyAttrs[0]); + +static const CK_ATTRIBUTE_TYPE secretKeyAttrs[] = { + CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_ENCRYPT, CKA_DECRYPT, CKA_SIGN, + CKA_VERIFY, CKA_WRAP, CKA_UNWRAP, CKA_VALUE +}; +static const CK_ULONG secretKeyAttrsCount = + sizeof(secretKeyAttrs)/sizeof(secretKeyAttrs[0]); + +static const CK_ATTRIBUTE_TYPE commonPubKeyAttrs[] = { + CKA_ENCRYPT, CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_WRAP, CKA_SUBJECT +}; +static const CK_ULONG commonPubKeyAttrsCount = + sizeof(commonPubKeyAttrs)/sizeof(commonPubKeyAttrs[0]); + +static const CK_ATTRIBUTE_TYPE rsaPubKeyAttrs[] = { + CKA_MODULUS, CKA_PUBLIC_EXPONENT +}; +static const CK_ULONG rsaPubKeyAttrsCount = + sizeof(rsaPubKeyAttrs)/sizeof(rsaPubKeyAttrs[0]); + +static const CK_ATTRIBUTE_TYPE dsaPubKeyAttrs[] = { + CKA_SUBPRIME, CKA_PRIME, CKA_BASE, CKA_VALUE +}; +static const CK_ULONG dsaPubKeyAttrsCount = + sizeof(dsaPubKeyAttrs)/sizeof(dsaPubKeyAttrs[0]); + +static const CK_ATTRIBUTE_TYPE dhPubKeyAttrs[] = { + CKA_PRIME, CKA_BASE, CKA_VALUE +}; +static const CK_ULONG dhPubKeyAttrsCount = + sizeof(dhPubKeyAttrs)/sizeof(dhPubKeyAttrs[0]); +#ifdef NSS_ENABLE_ECC +static const CK_ATTRIBUTE_TYPE ecPubKeyAttrs[] = { + CKA_EC_PARAMS, CKA_EC_POINT +}; +static const CK_ULONG ecPubKeyAttrsCount = + sizeof(ecPubKeyAttrs)/sizeof(ecPubKeyAttrs[0]); +#endif + +static const CK_ATTRIBUTE_TYPE commonPrivKeyAttrs[] = { + CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER, CKA_UNWRAP, CKA_SUBJECT, + CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_NETSCAPE_DB +}; +static const CK_ULONG commonPrivKeyAttrsCount = + sizeof(commonPrivKeyAttrs)/sizeof(commonPrivKeyAttrs[0]); + +static const CK_ATTRIBUTE_TYPE rsaPrivKeyAttrs[] = { + CKA_MODULUS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT, + CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT +}; +static const CK_ULONG rsaPrivKeyAttrsCount = + sizeof(rsaPrivKeyAttrs)/sizeof(rsaPrivKeyAttrs[0]); + +static const CK_ATTRIBUTE_TYPE dsaPrivKeyAttrs[] = { + CKA_SUBPRIME, CKA_PRIME, CKA_BASE, CKA_VALUE +}; +static const CK_ULONG dsaPrivKeyAttrsCount = + sizeof(dsaPrivKeyAttrs)/sizeof(dsaPrivKeyAttrs[0]); + +static const CK_ATTRIBUTE_TYPE dhPrivKeyAttrs[] = { + CKA_PRIME, CKA_BASE, CKA_VALUE +}; +static const CK_ULONG dhPrivKeyAttrsCount = + sizeof(dhPrivKeyAttrs)/sizeof(dhPrivKeyAttrs[0]); +#ifdef NSS_ENABLE_ECC +static const CK_ATTRIBUTE_TYPE ecPrivKeyAttrs[] = { + CKA_EC_PARAMS, CKA_VALUE +}; +static const CK_ULONG ecPrivKeyAttrsCount = + sizeof(ecPrivKeyAttrs)/sizeof(ecPrivKeyAttrs[0]); +#endif + +static const CK_ATTRIBUTE_TYPE certAttrs[] = { + CKA_CERTIFICATE_TYPE, CKA_VALUE, CKA_SUBJECT, CKA_ISSUER, CKA_SERIAL_NUMBER +}; +static const CK_ULONG certAttrsCount = + sizeof(certAttrs)/sizeof(certAttrs[0]); + +static const CK_ATTRIBUTE_TYPE trustAttrs[] = { + CKA_ISSUER, CKA_SERIAL_NUMBER, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH, + CKA_TRUST_SERVER_AUTH, CKA_TRUST_CLIENT_AUTH, CKA_TRUST_EMAIL_PROTECTION, + CKA_TRUST_CODE_SIGNING, CKA_TRUST_STEP_UP_APPROVED +}; +static const CK_ULONG trustAttrsCount = + sizeof(trustAttrs)/sizeof(trustAttrs[0]); + +static const CK_ATTRIBUTE_TYPE smimeAttrs[] = { + CKA_SUBJECT, CKA_NETSCAPE_EMAIL, CKA_NETSCAPE_SMIME_TIMESTAMP, CKA_VALUE +}; +static const CK_ULONG smimeAttrsCount = + sizeof(smimeAttrs)/sizeof(smimeAttrs[0]); + +static const CK_ATTRIBUTE_TYPE crlAttrs[] = { + CKA_SUBJECT, CKA_VALUE, CKA_NETSCAPE_URL, CKA_NETSCAPE_KRL +}; +static const CK_ULONG crlAttrsCount = + sizeof(crlAttrs)/sizeof(crlAttrs[0]); + +/* copy an object based on it's table */ +CK_RV +stfk_CopyTokenAttributes(SFTKObject *destObject,SFTKTokenObject *src_to, + const CK_ATTRIBUTE_TYPE *attrArray, CK_ULONG attrCount) +{ + SFTKAttribute *attribute; + SFTKAttribute *newAttribute; + CK_RV crv = CKR_OK; + unsigned int i; + + for (i=0; i < attrCount; i++) { + if (!sftk_hasAttribute(destObject,attrArray[i])) { + attribute =sftk_FindAttribute(&src_to->obj, attrArray[i]); + if (!attribute) { + continue; /* return CKR_ATTRIBUTE_VALUE_INVALID; */ + } + /* we need to copy the attribute since each attribute + * only has one set of link list pointers */ + newAttribute = sftk_NewAttribute( destObject, + sftk_attr_expand(&attribute->attrib)); + sftk_FreeAttribute(attribute); /* free the old attribute */ + if (!newAttribute) { + return CKR_HOST_MEMORY; + } + sftk_AddAttribute(destObject,newAttribute); + } + } + return crv; +} + +CK_RV +stfk_CopyTokenPrivateKey(SFTKObject *destObject,SFTKTokenObject *src_to) +{ + CK_RV crv; + CK_KEY_TYPE key_type; + SFTKAttribute *attribute; + + /* copy the common attributes for all keys first */ + crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs, + commonKeyAttrsCount); + if (crv != CKR_OK) { + goto fail; + } + /* copy the common attributes for all private keys next */ + crv = stfk_CopyTokenAttributes(destObject, src_to, commonPrivKeyAttrs, + commonKeyAttrsCount); + if (crv != CKR_OK) { + goto fail; + } + attribute =sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE); + PORT_Assert(attribute); /* if it wasn't here, ww should have failed + * copying the common attributes */ + if (!attribute) { + /* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but + * the fact is, the only reason we couldn't get the attribute would + * be a memory error or database error (an error in the 'device'). + * if we have a database error code, we could return it here */ + crv = CKR_DEVICE_ERROR; + goto fail; + } + key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue; + sftk_FreeAttribute(attribute); + + /* finally copy the attributes for various private key types */ + switch (key_type) { + case CKK_RSA: + crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPrivKeyAttrs, + rsaPrivKeyAttrsCount); + break; + case CKK_DSA: + crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPrivKeyAttrs, + dsaPrivKeyAttrsCount); + break; + case CKK_DH: + crv = stfk_CopyTokenAttributes(destObject, src_to, dhPrivKeyAttrs, + dhPrivKeyAttrsCount); + break; +#ifdef NSS_ENABLE_ECC + case CKK_EC: + crv = stfk_CopyTokenAttributes(destObject, src_to, ecPrivKeyAttrs, + ecPrivKeyAttrsCount); + break; +#endif + default: + crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types + * of token keys into our database. */ + } +fail: + return crv; +} + +CK_RV +stfk_CopyTokenPublicKey(SFTKObject *destObject,SFTKTokenObject *src_to) +{ + CK_RV crv; + CK_KEY_TYPE key_type; + SFTKAttribute *attribute; + + /* copy the common attributes for all keys first */ + crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs, + commonKeyAttrsCount); + if (crv != CKR_OK) { + goto fail; + } + + /* copy the common attributes for all public keys next */ + crv = stfk_CopyTokenAttributes(destObject, src_to, commonPubKeyAttrs, + commonPubKeyAttrsCount); + if (crv != CKR_OK) { + goto fail; + } + attribute =sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE); + PORT_Assert(attribute); /* if it wasn't here, ww should have failed + * copying the common attributes */ + if (!attribute) { + /* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but + * the fact is, the only reason we couldn't get the attribute would + * be a memory error or database error (an error in the 'device'). + * if we have a database error code, we could return it here */ + crv = CKR_DEVICE_ERROR; + goto fail; + } + key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue; + sftk_FreeAttribute(attribute); + + /* finally copy the attributes for various public key types */ + switch (key_type) { + case CKK_RSA: + crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPubKeyAttrs, + rsaPubKeyAttrsCount); + break; + case CKK_DSA: + crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPubKeyAttrs, + dsaPubKeyAttrsCount); + break; + case CKK_DH: + crv = stfk_CopyTokenAttributes(destObject, src_to, dhPubKeyAttrs, + dhPubKeyAttrsCount); + break; +#ifdef NSS_ENABLE_ECC + case CKK_EC: + crv = stfk_CopyTokenAttributes(destObject, src_to, ecPubKeyAttrs, + ecPubKeyAttrsCount); + break; +#endif + default: + crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types + * of token keys into our database. */ + } +fail: + return crv; +} +CK_RV +stfk_CopyTokenSecretKey(SFTKObject *destObject,SFTKTokenObject *src_to) +{ + CK_RV crv; + crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs, + commonKeyAttrsCount); + if (crv != CKR_OK) { + goto fail; + } + crv = stfk_CopyTokenAttributes(destObject, src_to, secretKeyAttrs, + secretKeyAttrsCount); +fail: + return crv; +} + +/* + * Copy a token object. We need to explicitly copy the relevant + * attributes since token objects don't store those attributes in + * the token itself. + */ +CK_RV +sftk_CopyTokenObject(SFTKObject *destObject,SFTKObject *srcObject) +{ + SFTKTokenObject *src_to = sftk_narrowToTokenObject(srcObject); + CK_RV crv; + + PORT_Assert(src_to); + if (src_to == NULL) { + return CKR_DEVICE_ERROR; /* internal state inconsistant */ + } + + crv = stfk_CopyTokenAttributes(destObject, src_to, commonAttrs, + commonAttrsCount); + if (crv != CKR_OK) { + goto fail; + } + switch (src_to->obj.objclass) { + case CKO_CERTIFICATE: + crv = stfk_CopyTokenAttributes(destObject, src_to, certAttrs, + certAttrsCount); + break; + case CKO_NETSCAPE_TRUST: + crv = stfk_CopyTokenAttributes(destObject, src_to, trustAttrs, + trustAttrsCount); + break; + case CKO_NETSCAPE_SMIME: + crv = stfk_CopyTokenAttributes(destObject, src_to, smimeAttrs, + smimeAttrsCount); + break; + case CKO_NETSCAPE_CRL: + crv = stfk_CopyTokenAttributes(destObject, src_to, crlAttrs, + crlAttrsCount); + break; + case CKO_PRIVATE_KEY: + crv = stfk_CopyTokenPrivateKey(destObject,src_to); + break; + case CKO_PUBLIC_KEY: + crv = stfk_CopyTokenPublicKey(destObject,src_to); + break; + case CKO_SECRET_KEY: + crv = stfk_CopyTokenSecretKey(destObject,src_to); + break; + default: + crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types + * of token keys into our database. */ + } +fail: + return crv; +} + +/* * copy the attributes from one object to another. Don't overwrite existing * attributes. NOTE: This is a pretty expensive operation since it * grabs the attribute locks for the src object for a *long* time. @@ -2396,7 +2939,7 @@ sftk_CopyObject(SFTKObject *destObject,SFTKObject *srcObject) unsigned int i; if (src_so == NULL) { - return CKR_DEVICE_ERROR; /* can't copy token objects yet */ + return sftk_CopyTokenObject(destObject,srcObject); } PZ_Lock(src_so->attributeLock); @@ -2420,6 +2963,7 @@ sftk_CopyObject(SFTKObject *destObject,SFTKObject *srcObject) } while (attribute != NULL); } PZ_Unlock(src_so->attributeLock); + return CKR_OK; } @@ -2602,7 +3146,7 @@ sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication, CK_FLAGS flags) { SFTKSession *session; - SFTKSlot *slot = sftk_SlotFromID(slotID); + SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE); if (slot == NULL) return NULL; @@ -2676,7 +3220,10 @@ sftk_SessionFromHandle(CK_SESSION_HANDLE handle) { SFTKSlot *slot = sftk_SlotFromSessionHandle(handle); SFTKSession *session; - PZLock *lock = SFTK_SESSION_LOCK(slot,handle); + PZLock *lock; + + if (!slot) return NULL; + lock = SFTK_SESSION_LOCK(slot,handle); PZ_Lock(lock); sftkqueue_find(session,handle,slot->head,slot->sessHashSize); diff --git a/security/nss/lib/softoken/tlsprf.c b/security/nss/lib/softoken/tlsprf.c index 8bf589dff..23e996d5f 100644 --- a/security/nss/lib/softoken/tlsprf.c +++ b/security/nss/lib/softoken/tlsprf.c @@ -38,132 +38,10 @@ /* $Id$ */ #include "pkcs11i.h" -#include "sechash.h" -#include "alghmac.h" +#include "blapi.h" #define SFTK_OFFSETOF(str, memb) ((PRPtrdiff)(&(((str *)0)->memb))) -#define PHASH_STATE_MAX_LEN 20 - -/* TLS P_hash function */ -static SECStatus -sftk_P_hash(HASH_HashType hashType, const SECItem *secret, const char *label, - SECItem *seed, SECItem *result, PRBool isFIPS) -{ - unsigned char state[PHASH_STATE_MAX_LEN]; - unsigned char outbuf[PHASH_STATE_MAX_LEN]; - unsigned int state_len = 0, label_len = 0, outbuf_len = 0, chunk_size; - unsigned int remaining; - unsigned char *res; - SECStatus status; - HMACContext *cx; - SECStatus rv = SECFailure; - const SECHashObject *hashObj = &SECRawHashObjects[hashType]; - - PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len)); - PORT_Assert((seed != NULL) && (seed->data != NULL)); - PORT_Assert((result != NULL) && (result->data != NULL)); - - remaining = result->len; - res = result->data; - - if (label != NULL) - label_len = PORT_Strlen(label); - - cx = HMAC_Create(hashObj, secret->data, secret->len, isFIPS); - if (cx == NULL) - goto loser; - - /* initialize the state = A(1) = HMAC_hash(secret, seed) */ - HMAC_Begin(cx); - HMAC_Update(cx, (unsigned char *)label, label_len); - HMAC_Update(cx, seed->data, seed->len); - status = HMAC_Finish(cx, state, &state_len, PHASH_STATE_MAX_LEN); - if (status != SECSuccess) - goto loser; - - /* generate a block at a time until we're done */ - while (remaining > 0) { - - HMAC_Begin(cx); - HMAC_Update(cx, state, state_len); - if (label_len) - HMAC_Update(cx, (unsigned char *)label, label_len); - HMAC_Update(cx, seed->data, seed->len); - status = HMAC_Finish(cx, outbuf, &outbuf_len, PHASH_STATE_MAX_LEN); - if (status != SECSuccess) - goto loser; - - /* Update the state = A(i) = HMAC_hash(secret, A(i-1)) */ - HMAC_Begin(cx); - HMAC_Update(cx, state, state_len); - status = HMAC_Finish(cx, state, &state_len, PHASH_STATE_MAX_LEN); - if (status != SECSuccess) - goto loser; - - chunk_size = PR_MIN(outbuf_len, remaining); - PORT_Memcpy(res, &outbuf, chunk_size); - res += chunk_size; - remaining -= chunk_size; - } - - rv = SECSuccess; - -loser: - /* if (cx) HMAC_Destroy(cx); */ - /* clear out state so it's not left on the stack */ - if (cx) HMAC_Destroy(cx); - PORT_Memset(state, 0, sizeof(state)); - PORT_Memset(outbuf, 0, sizeof(outbuf)); - return rv; -} - -SECStatus -sftk_PRF(const SECItem *secret, const char *label, SECItem *seed, - SECItem *result, PRBool isFIPS) -{ - SECStatus rv = SECFailure, status; - unsigned int i; - SECItem tmp = { siBuffer, NULL, 0}; - SECItem S1; - SECItem S2; - - PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len)); - PORT_Assert((seed != NULL) && (seed->data != NULL)); - PORT_Assert((result != NULL) && (result->data != NULL)); - - S1.type = siBuffer; - S1.len = (secret->len / 2) + (secret->len & 1); - S1.data = secret->data; - - S2.type = siBuffer; - S2.len = S1.len; - S2.data = secret->data + (secret->len - S2.len); - - tmp.data = (unsigned char*)PORT_Alloc(result->len); - if (tmp.data == NULL) - goto loser; - tmp.len = result->len; - - status = sftk_P_hash(HASH_AlgMD5, &S1, label, seed, result, isFIPS); - if (status != SECSuccess) - goto loser; - - status = sftk_P_hash(HASH_AlgSHA1, &S2, label, seed, &tmp, isFIPS); - if (status != SECSuccess) - goto loser; - - for (i = 0; i < result->len; i++) - result->data[i] ^= tmp.data[i]; - - rv = SECSuccess; - -loser: - if (tmp.data != NULL) - PORT_ZFree(tmp.data, tmp.len); - return rv; -} - static void sftk_TLSPRFNull(void *data, PRBool freeit) { return; @@ -243,7 +121,7 @@ sftk_TLSPRFUpdate(TLSPRFContext *cx, sigItem.data = sig; sigItem.len = maxLen; - rv = sftk_PRF(&secretItem, NULL, &seedItem, &sigItem, cx->cxIsFIPS); + rv = TLS_PRF(&secretItem, NULL, &seedItem, &sigItem, cx->cxIsFIPS); if (rv == SECSuccess && sigLen != NULL) *sigLen = sigItem.len; return rv; diff --git a/security/nss/lib/ssl/config.mk b/security/nss/lib/ssl/config.mk index d506b12a9..35e4147b5 100644 --- a/security/nss/lib/ssl/config.mk +++ b/security/nss/lib/ssl/config.mk @@ -52,6 +52,7 @@ ifdef NS_USE_GCC EXTRA_SHARED_LIBS += \ -L$(DIST)/lib \ -lnss3 \ + -L$(NSPR_LIB_DIR) \ -lplc4 \ -lplds4 \ -lnspr4 \ @@ -59,20 +60,45 @@ EXTRA_SHARED_LIBS += \ else # ! NS_USE_GCC EXTRA_SHARED_LIBS += \ $(DIST)/lib/nss3.lib \ - $(DIST)/lib/$(NSPR31_LIB_PREFIX)plc4.lib \ - $(DIST)/lib/$(NSPR31_LIB_PREFIX)plds4.lib \ - $(DIST)/lib/$(NSPR31_LIB_PREFIX)nspr4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plc4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)plds4.lib \ + $(NSPR_LIB_DIR)/$(NSPR31_LIB_PREFIX)nspr4.lib \ $(NULL) endif # NS_USE_GCC +# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS) +CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)freebl.$(LIB_SUFFIX) +CRYPTODIR=../freebl +ifdef MOZILLA_SECURITY_BUILD + CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)crypto.$(LIB_SUFFIX) + CRYPTODIR=../crypto +endif + +EXTRA_LIBS += \ + $(CRYPTOLIB) \ + $(NULL) + else +# $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS) +CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)freebl.$(LIB_SUFFIX) +CRYPTODIR=../freebl +ifdef MOZILLA_SECURITY_BUILD + CRYPTOLIB=$(DIST)/lib/$(LIB_PREFIX)crypto.$(LIB_SUFFIX) + CRYPTODIR=../crypto +endif + +EXTRA_LIBS += \ + $(CRYPTOLIB) \ + $(NULL) + # $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS) # $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX. EXTRA_SHARED_LIBS += \ - -L$(DIST)/lib/ \ + -L$(DIST)/lib \ -lnss3 \ + -L$(NSPR_LIB_DIR) \ -lplc4 \ -lplds4 \ -lnspr4 \ @@ -90,6 +116,10 @@ ifeq ($(OS_TARGET),SunOS) # The -R '$ORIGIN' linker option instructs this library to search for its # dependencies in the same directory where it resides. MKSHLIB += -R '$$ORIGIN' +#EXTRA_SHARED_LIBS += -ldl -lrt -lc -z defs endif endif + +# indicates dependency on freebl static lib +$(SHARED_LIBRARY): $(CRYPTOLIB) diff --git a/security/nss/lib/ssl/derive.c b/security/nss/lib/ssl/derive.c new file mode 100644 index 000000000..c00822bee --- /dev/null +++ b/security/nss/lib/ssl/derive.c @@ -0,0 +1,481 @@ +/* + * Key Derivation that doesn't use PKCS11 + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2005 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +/* $Id$ */ + +#include "ssl.h" /* prereq to sslimpl.h */ +#include "certt.h" /* prereq to sslimpl.h */ +#include "keythi.h" /* prereq to sslimpl.h */ +#include "sslimpl.h" +#include "blapi.h" + +/* make this a macro! */ +#ifdef NOT_A_MACRO +static void +buildSSLKey(unsigned char * keyBlock, unsigned int keyLen, SECItem * result) +{ + result->type = siBuffer; + result->data = keyBlock; + result->len = keyLen; +} +#else +#define buildSSLKey(keyBlock, keyLen, result) \ +{ \ + (result)->type = siBuffer; \ + (result)->data = keyBlock; \ + (result)->len = keyLen; \ +} +#endif + +/* + * SSL Key generation given pre master secret + */ +#ifndef NUM_MIXERS +#define NUM_MIXERS 9 +#endif +static const char * const mixers[NUM_MIXERS] = { + "A", + "BB", + "CCC", + "DDDD", + "EEEEE", + "FFFFFF", + "GGGGGGG", + "HHHHHHHH", + "IIIIIIIII" +}; + + +SECStatus +ssl3_KeyAndMacDeriveBypass( + ssl3CipherSpec * pwSpec, + const unsigned char * cr, + const unsigned char * sr, + PRBool isTLS, + PRBool isExport) +{ + const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def; + unsigned char * key_block = pwSpec->key_block; + unsigned char * key_block2 = NULL; + unsigned int block_bytes = 0; + unsigned int block_needed = 0; + unsigned int i; + unsigned int keySize; /* actual size of cipher keys */ + unsigned int effKeySize; /* effective size of cipher keys */ + unsigned int macSize; /* size of MAC secret */ + unsigned int IVSize; /* size of IV */ + SECStatus rv = SECFailure; + SECStatus status = SECSuccess; + PRBool isFIPS = PR_FALSE; + + SECItem srcr; + SECItem crsr; + + unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2]; + unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; + PRUint64 md5buf[22]; + PRUint64 shabuf[40]; + +#define md5Ctx ((MD5Context *)md5buf) +#define shaCtx ((SHA1Context *)shabuf) + + static const SECItem zed = { siBuffer, NULL, 0 }; + + if (pwSpec->msItem.data == NULL || + pwSpec->msItem.len != SSL3_MASTER_SECRET_LENGTH) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return rv; + } + + /* figure out how much is needed */ + macSize = pwSpec->mac_size; + keySize = cipher_def->key_size; + effKeySize = cipher_def->secret_key_size; + IVSize = cipher_def->iv_size; + if (keySize == 0) { + effKeySize = IVSize = 0; /* only MACing */ + } + block_needed = 2 * (macSize + effKeySize + ((!isExport) * IVSize)); + + /* + * clear out our returned keys so we can recover on failure + */ + pwSpec->client.write_key_item = zed; + pwSpec->client.write_mac_key_item = zed; + pwSpec->server.write_key_item = zed; + pwSpec->server.write_mac_key_item = zed; + + /* initialize the server random, client random block */ + srcr.type = siBuffer; + srcr.data = srcrdata; + srcr.len = sizeof srcrdata; + PORT_Memcpy(srcrdata, sr, SSL3_RANDOM_LENGTH); + PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, cr, SSL3_RANDOM_LENGTH); + + /* initialize the client random, server random block */ + crsr.type = siBuffer; + crsr.data = crsrdata; + crsr.len = sizeof crsrdata; + PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH); + PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH); + + /* + * generate the key material: + */ + if (isTLS) { + SECItem keyblk; + + keyblk.type = siBuffer; + keyblk.data = key_block; + keyblk.len = block_needed; + + status = TLS_PRF(&pwSpec->msItem, "key expansion", &srcr, &keyblk, + isFIPS); + if (status != SECSuccess) { + goto key_and_mac_derive_fail; + } + block_bytes = keyblk.len; + } else { + /* key_block = + * MD5(master_secret + SHA('A' + master_secret + + * ServerHello.random + ClientHello.random)) + + * MD5(master_secret + SHA('BB' + master_secret + + * ServerHello.random + ClientHello.random)) + + * MD5(master_secret + SHA('CCC' + master_secret + + * ServerHello.random + ClientHello.random)) + + * [...]; + */ + int made = 0; + for (i = 0; made < block_needed && i < NUM_MIXERS; ++i) { + unsigned int outLen; + unsigned char sha_out[SHA1_LENGTH]; + + SHA1_Begin(shaCtx); + SHA1_Update(shaCtx, (unsigned char*)(mixers[i]), i+1); + SHA1_Update(shaCtx, pwSpec->msItem.data, pwSpec->msItem.len); + SHA1_Update(shaCtx, srcr.data, srcr.len); + SHA1_End(shaCtx, sha_out, &outLen, SHA1_LENGTH); + PORT_Assert(outLen == SHA1_LENGTH); + + MD5_Begin(md5Ctx); + MD5_Update(md5Ctx, pwSpec->msItem.data, pwSpec->msItem.len); + MD5_Update(md5Ctx, sha_out, outLen); + MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH); + PORT_Assert(outLen == MD5_LENGTH); + made += MD5_LENGTH; + } + block_bytes = made; + } + PORT_Assert(block_bytes >= block_needed); + PORT_Assert(block_bytes <= sizeof pwSpec->key_block); + + /* + * Put the key material where it goes. + */ + key_block2 = key_block + block_bytes; + i = 0; /* now shows how much consumed */ + + /* + * The key_block is partitioned as follows: + * client_write_MAC_secret[CipherSpec.hash_size] + */ + buildSSLKey(&key_block[i],macSize, &pwSpec->client.write_mac_key_item); + i += macSize; + + /* + * server_write_MAC_secret[CipherSpec.hash_size] + */ + buildSSLKey(&key_block[i],macSize, &pwSpec->server.write_mac_key_item); + i += macSize; + + if (!keySize) { + /* only MACing */ + buildSSLKey(NULL, 0, &pwSpec->client.write_key_item); + buildSSLKey(NULL, 0, &pwSpec->server.write_key_item); + buildSSLKey(NULL, 0, &pwSpec->client.write_iv_item); + buildSSLKey(NULL, 0, &pwSpec->server.write_iv_item); + } else if (!isExport) { + /* + ** Generate Domestic write keys and IVs. + ** client_write_key[CipherSpec.key_material] + */ + buildSSLKey(&key_block[i], keySize, &pwSpec->client.write_key_item); + i += keySize; + + /* + ** server_write_key[CipherSpec.key_material] + */ + buildSSLKey(&key_block[i], keySize, &pwSpec->server.write_key_item); + i += keySize; + + if (IVSize > 0) { + /* + ** client_write_IV[CipherSpec.IV_size] + */ + buildSSLKey(&key_block[i], IVSize, &pwSpec->client.write_iv_item); + i += IVSize; + + /* + ** server_write_IV[CipherSpec.IV_size] + */ + buildSSLKey(&key_block[i], IVSize, &pwSpec->server.write_iv_item); + i += IVSize; + } + PORT_Assert(i <= block_bytes); + + } else if (!isTLS) { + /* + ** Generate SSL3 Export write keys and IVs. + */ + unsigned int outLen; + + /* + ** client_write_key[CipherSpec.key_material] + ** final_client_write_key = MD5(client_write_key + + ** ClientHello.random + ServerHello.random); + */ + MD5_Begin(md5Ctx); + MD5_Update(md5Ctx, &key_block[i], effKeySize); + MD5_Update(md5Ctx, crsr.data, crsr.len); + MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH); + i += effKeySize; + buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item); + key_block2 += keySize; + + /* + ** server_write_key[CipherSpec.key_material] + ** final_server_write_key = MD5(server_write_key + + ** ServerHello.random + ClientHello.random); + */ + MD5_Begin(md5Ctx); + MD5_Update(md5Ctx, &key_block[i], effKeySize); + MD5_Update(md5Ctx, srcr.data, srcr.len); + MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH); + i += effKeySize; + buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item); + key_block2 += keySize; + PORT_Assert(i <= block_bytes); + + if (IVSize) { + /* + ** client_write_IV = + ** MD5(ClientHello.random + ServerHello.random); + */ + MD5_Begin(md5Ctx); + MD5_Update(md5Ctx, crsr.data, crsr.len); + MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH); + buildSSLKey(key_block2, IVSize, &pwSpec->client.write_iv_item); + key_block2 += IVSize; + + /* + ** server_write_IV = + ** MD5(ServerHello.random + ClientHello.random); + */ + MD5_Begin(md5Ctx); + MD5_Update(md5Ctx, srcr.data, srcr.len); + MD5_End(md5Ctx, key_block2, &outLen, MD5_LENGTH); + buildSSLKey(key_block2, IVSize, &pwSpec->server.write_iv_item); + key_block2 += IVSize; + } + + PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block); + } else { + /* + ** Generate TLS Export write keys and IVs. + */ + SECItem secret ; + SECItem keyblk ; + + secret.type = siBuffer; + keyblk.type = siBuffer; + /* + ** client_write_key[CipherSpec.key_material] + ** final_client_write_key = PRF(client_write_key, + ** "client write key", + ** client_random + server_random); + */ + secret.data = &key_block[i]; + secret.len = effKeySize; + i += effKeySize; + keyblk.data = key_block2; + keyblk.len = keySize; + status = TLS_PRF(&secret, "client write key", &crsr, &keyblk, isFIPS); + if (status != SECSuccess) { + goto key_and_mac_derive_fail; + } + buildSSLKey(key_block2, keySize, &pwSpec->client.write_key_item); + key_block2 += keySize; + + /* + ** server_write_key[CipherSpec.key_material] + ** final_server_write_key = PRF(server_write_key, + ** "server write key", + ** client_random + server_random); + */ + secret.data = &key_block[i]; + secret.len = effKeySize; + i += effKeySize; + keyblk.data = key_block2; + keyblk.len = keySize; + status = TLS_PRF(&secret, "server write key", &crsr, &keyblk, isFIPS); + if (status != SECSuccess) { + goto key_and_mac_derive_fail; + } + buildSSLKey(key_block2, keySize, &pwSpec->server.write_key_item); + key_block2 += keySize; + + /* + ** iv_block = PRF("", "IV block", client_random + server_random); + ** client_write_IV[SecurityParameters.IV_size] + ** server_write_IV[SecurityParameters.IV_size] + */ + if (IVSize) { + secret.data = NULL; + secret.len = 0; + keyblk.data = key_block2; + keyblk.len = 2 * IVSize; + status = TLS_PRF(&secret, "IV block", &crsr, &keyblk, isFIPS); + if (status != SECSuccess) { + goto key_and_mac_derive_fail; + } + buildSSLKey(key_block2, IVSize, &pwSpec->client.write_iv_item); + buildSSLKey(key_block2 + IVSize, IVSize, &pwSpec->server.write_iv_item); + key_block2 += 2 * IVSize; + } + PORT_Assert(key_block2 - key_block <= sizeof pwSpec->key_block); + } + rv = SECSuccess; + +key_and_mac_derive_fail: + + MD5_DestroyContext(md5Ctx, PR_FALSE); + SHA1_DestroyContext(shaCtx, PR_FALSE); + + if (rv != SECSuccess) { + PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); + } + + return rv; +} + + +/* derive the Master Secret from the PMS */ +/* Presently, this is only done wtih RSA PMS, os isRSA is always true. */ +SECStatus +ssl3_MasterKeyDeriveBypass( + ssl3CipherSpec * pwSpec, + const unsigned char * cr, + const unsigned char * sr, + const SECItem * pms, + PRBool isTLS, + PRBool isRSA) +{ + unsigned char * key_block = pwSpec->key_block; + SECStatus rv = SECSuccess; + PRBool isFIPS = PR_FALSE; + + SECItem crsr; + + unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2]; + PRUint64 md5buf[22]; + PRUint64 shabuf[40]; + +#define md5Ctx ((MD5Context *)md5buf) +#define shaCtx ((SHA1Context *)shabuf) + + /* first do the consistancy checks */ + if (isRSA) { + PORT_Assert(pms->len == SSL3_RSA_PMS_LENGTH); + if (pms->len != SSL3_RSA_PMS_LENGTH) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + /* caller must test PMS version for rollback */ + } + + /* initialize the client random, server random block */ + crsr.type = siBuffer; + crsr.data = crsrdata; + crsr.len = sizeof crsrdata; + PORT_Memcpy(crsrdata, cr, SSL3_RANDOM_LENGTH); + PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, sr, SSL3_RANDOM_LENGTH); + + /* finally do the key gen */ + if (isTLS) { + SECItem master = { siBuffer, NULL, 0 }; + + master.data = key_block; + master.len = SSL3_MASTER_SECRET_LENGTH; + + rv = TLS_PRF(pms, "master secret", &crsr, &master, isFIPS); + if (rv != SECSuccess) { + PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); + } + } else { + int i; + int made = 0; + for (i = 0; i < 3; i++) { + unsigned int outLen; + unsigned char sha_out[SHA1_LENGTH]; + + SHA1_Begin(shaCtx); + SHA1_Update(shaCtx, (unsigned char*) mixers[i], i+1); + SHA1_Update(shaCtx, pms->data, pms->len); + SHA1_Update(shaCtx, crsr.data, crsr.len); + SHA1_End(shaCtx, sha_out, &outLen, SHA1_LENGTH); + PORT_Assert(outLen == SHA1_LENGTH); + + MD5_Begin(md5Ctx); + MD5_Update(md5Ctx, pms->data, pms->len); + MD5_Update(md5Ctx, sha_out, outLen); + MD5_End(md5Ctx, key_block + made, &outLen, MD5_LENGTH); + PORT_Assert(outLen == MD5_LENGTH); + made += outLen; + } + } + + /* store the results */ + PORT_Memcpy(pwSpec->raw_master_secret, key_block, + SSL3_MASTER_SECRET_LENGTH); + pwSpec->msItem.data = pwSpec->raw_master_secret; + pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH; + + return rv; +} + + diff --git a/security/nss/lib/ssl/manifest.mn b/security/nss/lib/ssl/manifest.mn index f49a8e038..6428ce5c7 100644 --- a/security/nss/lib/ssl/manifest.mn +++ b/security/nss/lib/ssl/manifest.mn @@ -55,6 +55,7 @@ MODULE = nss MAPFILE = $(OBJDIR)/ssl.def CSRCS = \ + derive.c \ emulate.c \ prelib.c \ ssl3con.c \ @@ -77,14 +78,13 @@ CSRCS = \ cmpcert.c \ nsskea.c \ sslinfo.c \ + ssl3ecc.c \ $(NULL) - -REQUIRES = dbm - ifdef NSS_ENABLE_ECC DEFINES += -DNSS_ENABLE_ECC endif LIBRARY_NAME = ssl LIBRARY_VERSION = 3 + diff --git a/security/nss/lib/ssl/nsskea.c b/security/nss/lib/ssl/nsskea.c index b61ac71e4..beafc506e 100644 --- a/security/nss/lib/ssl/nsskea.c +++ b/security/nss/lib/ssl/nsskea.c @@ -58,12 +58,6 @@ NSS_FindCertKEAType(CERTCertificate * cert) case SEC_OID_PKCS1_RSA_ENCRYPTION: keaType = kt_rsa; break; - case SEC_OID_MISSI_KEA_DSS_OLD: - case SEC_OID_MISSI_KEA_DSS: - case SEC_OID_MISSI_DSS_OLD: - case SEC_OID_MISSI_DSS: - keaType = kt_fortezza; - break; case SEC_OID_X942_DIFFIE_HELMAN_KEY: keaType = kt_dh; break; diff --git a/security/nss/lib/ssl/preenc.h b/security/nss/lib/ssl/preenc.h index 9b6d3104a..f7c9093cb 100644 --- a/security/nss/lib/ssl/preenc.h +++ b/security/nss/lib/ssl/preenc.h @@ -1,8 +1,7 @@ /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ /* - * Functions and types used by https servers to send (download) pre-encrypted - * files over SSL connections that use Fortezza ciphersuites. + * Fortezza support is removed. * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 @@ -41,6 +40,11 @@ * ***** END LICENSE BLOCK ***** */ /* $Id$ */ +/* Fortezza support is removed. + * This file remains so that old programs will continue to compile, + * But this functionality is no longer supported or implemented. + */ + #include "seccomon.h" #include "prio.h" @@ -48,53 +52,44 @@ typedef struct PEHeaderStr PEHeader; #define PE_MIME_TYPE "application/pre-encrypted" - -/* - * unencrypted header. The 'top' half of this header is generic. The union - * is type specific, and may include bulk cipher type information - * (Fortezza supports only Fortezza Bulk encryption). Only fortezza - * pre-encrypted is defined. - */ typedef struct PEFortezzaHeaderStr PEFortezzaHeader; typedef struct PEFortezzaGeneratedHeaderStr PEFortezzaGeneratedHeader; typedef struct PEFixedKeyHeaderStr PEFixedKeyHeader; typedef struct PERSAKeyHeaderStr PERSAKeyHeader; struct PEFortezzaHeaderStr { - unsigned char key[12]; /* Ks wrapped MEK */ - unsigned char iv[24]; /* iv for this MEK */ - unsigned char hash[20]; /* SHA hash of file */ - unsigned char serial[8]; /* serial number of the card that owns - * Ks */ + unsigned char key[12]; + unsigned char iv[24]; + unsigned char hash[20]; + unsigned char serial[8]; }; struct PEFortezzaGeneratedHeaderStr { - unsigned char key[12]; /* TEK wrapped MEK */ - unsigned char iv[24]; /* iv for this MEK */ - unsigned char hash[20]; /* SHA hash of file */ - unsigned char Ra[128]; /* RA to generate TEK */ - unsigned char Y[128]; /* Y to generate TEK */ + unsigned char key[12]; + unsigned char iv[24]; + unsigned char hash[20]; + unsigned char Ra[128]; + unsigned char Y[128]; }; struct PEFixedKeyHeaderStr { - unsigned char pkcs11Mech[4]; /* Symetric key operation */ - unsigned char labelLen[2]; /* length of the token label */ - unsigned char keyIDLen[2]; /* length of the token Key ID */ - unsigned char ivLen[2]; /* length of IV */ - unsigned char keyLen[2]; /* length of key (DES3_ECB encrypted) */ - unsigned char data[1]; /* start of data */ + unsigned char pkcs11Mech[4]; + unsigned char labelLen[2]; + unsigned char keyIDLen[2]; + unsigned char ivLen[2]; + unsigned char keyLen[2]; + unsigned char data[1]; }; struct PERSAKeyHeaderStr { - unsigned char pkcs11Mech[4]; /* Symetric key operation */ - unsigned char issuerLen[2]; /* length of cert issuer */ - unsigned char serialLen[2]; /* length of the cert serial */ - unsigned char ivLen[2]; /* length of IV */ - unsigned char keyLen[2]; /* length of key (RSA encrypted) */ - unsigned char data[1]; /* start of data */ + unsigned char pkcs11Mech[4]; + unsigned char issuerLen[2]; + unsigned char serialLen[2]; + unsigned char ivLen[2]; + unsigned char keyLen[2]; + unsigned char data[1]; }; -/* macros to get at the variable length data fields */ #define PEFIXED_Label(header) (header->data) #define PEFIXED_KeyID(header) (&header->data[GetInt2(header->labelLen)]) #define PEFIXED_IV(header) (&header->data[GetInt2(header->labelLen)\ @@ -108,10 +103,10 @@ struct PERSAKeyHeaderStr { #define PERSA_Key(header) (&header->data[GetInt2(header->issuerLen)\ +GetInt2(header->serialLen)+GetInt2(header->keyLen)]) struct PEHeaderStr { - unsigned char magic [2]; /* always 0xC0DE */ - unsigned char len [2]; /* length of PEHeader */ - unsigned char type [2]; /* FORTEZZA, DIFFIE-HELMAN, RSA */ - unsigned char version[2]; /* version number: 1.0 */ + unsigned char magic [2]; + unsigned char len [2]; + unsigned char type [2]; + unsigned char version[2]; union { PEFortezzaHeader fortezza; PEFortezzaGeneratedHeader g_fortezza; @@ -124,12 +119,9 @@ struct PEHeaderStr { #define PE_INTRO_LEN 4 #define PE_BASE_HEADER_LEN 8 -#define PRE_BLOCK_SIZE 8 /* for decryption blocks */ +#define PRE_BLOCK_SIZE 8 -/* - * Platform neutral encode/decode macros. - */ #define GetInt2(c) ((c[0] << 8) | c[1]) #define GetInt4(c) (((unsigned long)c[0] << 24)|((unsigned long)c[1] << 16)\ |((unsigned long)c[2] << 8)| ((unsigned long)c[3])) @@ -137,28 +129,18 @@ struct PEHeaderStr { #define PutInt4(c,i) ((c[0]=((i) >> 24) & 0xff),(c[1]=((i) >> 16) & 0xff),\ (c[2] = ((i) >> 8) & 0xff), (c[3] = (i) & 0xff)) -/* - * magic numbers. - */ #define PRE_MAGIC 0xc0de #define PRE_VERSION 0x1010 -#define PRE_FORTEZZA_FILE 0x00ff /* pre-encrypted file on disk */ -#define PRE_FORTEZZA_STREAM 0x00f5 /* pre-encrypted file in stream */ -#define PRE_FORTEZZA_GEN_STREAM 0x00f6 /* Generated pre-encrypted file */ -#define PRE_FIXED_FILE 0x000f /* fixed key on disk */ -#define PRE_RSA_FILE 0x001f /* RSA in file */ -#define PRE_FIXED_STREAM 0x0005 /* fixed key in stream */ - -/* - * internal implementation info - */ - +#define PRE_FORTEZZA_FILE 0x00ff +#define PRE_FORTEZZA_STREAM 0x00f5 +#define PRE_FORTEZZA_GEN_STREAM 0x00f6 +#define PRE_FIXED_FILE 0x000f +#define PRE_RSA_FILE 0x001f +#define PRE_FIXED_STREAM 0x0005 -/* convert an existing stream header to a version with local parameters */ PEHeader *SSL_PreencryptedStreamToFile(PRFileDesc *fd, PEHeader *, int *headerSize); -/* convert an existing file header to one suitable for streaming out */ PEHeader *SSL_PreencryptedFileToStream(PRFileDesc *fd, PEHeader *, int *headerSize); diff --git a/security/nss/lib/ssl/prelib.c b/security/nss/lib/ssl/prelib.c index b24399b98..c63483924 100644 --- a/security/nss/lib/ssl/prelib.c +++ b/security/nss/lib/ssl/prelib.c @@ -50,205 +50,18 @@ #include "preenc.h" #include "pk11func.h" -static unsigned char fromHex(char x) { - if ((x >= '0') && (x <= '9')) return x-'0'; - if ((x >= 'a') && (x <= 'f')) return x-'a'+10; - return x-'A'+10; -} - PEHeader *SSL_PreencryptedStreamToFile(PRFileDesc *fd, PEHeader *inHeader, - int *headerSize) + int *headerSize) { - PK11SymKey *key, *tek, *Ks; - sslSocket *ss; - PK11SlotInfo *slot; - CK_TOKEN_INFO info; - int oldHeaderSize; - PEHeader *header; - SECStatus rv; - SECItem item; - int i; - - if (fd == NULL) { - /* XXX set an error */ - return NULL; - } - - ss = ssl_FindSocket(fd); - if (ss == NULL) { - return NULL; - } - - PORT_Assert(ss->ssl3 != NULL); - if (ss->ssl3 == NULL) { - return NULL; - } - - if (GetInt2(inHeader->magic) != PRE_MAGIC) { - return NULL; - } - - oldHeaderSize = GetInt2(inHeader->len); - header = (PEHeader *) PORT_ZAlloc(oldHeaderSize); - if (header == NULL) { - return NULL; - } - - switch (GetInt2(inHeader->type)) { - case PRE_FORTEZZA_FILE: - case PRE_FORTEZZA_GEN_STREAM: - case PRE_FIXED_FILE: - case PRE_RSA_FILE: - default: - *headerSize = oldHeaderSize; - PORT_Memcpy(header,inHeader,oldHeaderSize); - return header; - - case PRE_FORTEZZA_STREAM: - *headerSize = PE_BASE_HEADER_LEN + sizeof(PEFortezzaHeader); - PutInt2(header->magic,PRE_MAGIC); - PutInt2(header->len,*headerSize); - PutInt2(header->type, PRE_FORTEZZA_FILE); - PORT_Memcpy(header->version,inHeader->version,sizeof(header->version)); - PORT_Memcpy(header->u.fortezza.hash,inHeader->u.fortezza.hash, - sizeof(header->u.fortezza.hash)); - PORT_Memcpy(header->u.fortezza.iv,inHeader->u.fortezza.iv, - sizeof(header->u.fortezza.iv)); - - /* get the kea context from the session */ - tek = ss->ssl3->fortezza.tek; - if (tek == NULL) { - PORT_Free(header); - return NULL; - } - - - /* get the slot and the serial number */ - slot = PK11_GetSlotFromKey(tek); - if (slot == NULL) { - PORT_Free(header); - return NULL; - } - rv = PK11_GetTokenInfo(slot,&info); - if (rv != SECSuccess) { - PORT_Free(header); - PK11_FreeSlot(slot); - return NULL; - } - - /* Look up the Token Fixed Key */ - Ks = PK11_FindFixedKey(slot, CKM_SKIPJACK_WRAP, NULL, ss->pkcs11PinArg); - PK11_FreeSlot(slot); - if (Ks == NULL) { - PORT_Free(header); - return NULL; - } - - /* unwrap the key with the TEK */ - item.data = inHeader->u.fortezza.key; - item.len = sizeof(inHeader->u.fortezza.key); - key = PK11_UnwrapSymKey(tek,CKM_SKIPJACK_WRAP, - NULL, &item, CKM_SKIPJACK_CBC64, CKA_DECRYPT, 0); - if (key == NULL) { - PORT_Free(header); - PK11_FreeSymKey(Ks); - return NULL; - } - - /* rewrap with the local Ks */ - item.data = header->u.fortezza.key; - item.len = sizeof(header->u.fortezza.key); - rv = PK11_WrapSymKey(CKM_SKIPJACK_WRAP, NULL, Ks, key, &item); - PK11_FreeSymKey(Ks); - PK11_FreeSymKey(key); - if (rv != SECSuccess) { - PORT_Free(header); - return NULL; - } - - /* copy our local serial number into header */ - for (i=0; i < sizeof(header->u.fortezza.serial); i++) { - header->u.fortezza.serial[i] = - (fromHex(info.serialNumber[i*2]) << 4) | - fromHex(info.serialNumber[i*2 + 1]); - } - break; - case PRE_FIXED_STREAM: - /* not implemented yet */ - PORT_Free(header); - return NULL; - } - - return(header); + PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); + return NULL; } -/* - * this one needs to allocate space and work for RSA & FIXED key files as well - */ PEHeader *SSL_PreencryptedFileToStream(PRFileDesc *fd, PEHeader *header, int *headerSize) { - PK11SymKey *key, *tek, *Ks; - sslSocket *ss; - PK11SlotInfo *slot; - SECStatus rv; - SECItem item; - - *headerSize = 0; /* hack */ - - if (fd == NULL) { - /* XXX set an error */ - return NULL; - } - - ss = ssl_FindSocket(fd); - if (ss == NULL) { - return NULL; - } - - PORT_Assert(ss->ssl3 != NULL); - if (ss->ssl3 == NULL) { - return NULL; - } - - /* get the kea context from the session */ - tek = ss->ssl3->fortezza.tek; - if (tek == NULL) { - return NULL; - } - - slot = PK11_GetSlotFromKey(tek); - if (slot == NULL) return NULL; - Ks = PK11_FindFixedKey(slot, CKM_SKIPJACK_WRAP, NULL, PK11_GetWindow(tek)); - PK11_FreeSlot(slot); - if (Ks == NULL) return NULL; - - - /* unwrap with the local Ks */ - item.data = header->u.fortezza.key; - item.len = sizeof(header->u.fortezza.key); - /* rewrap the key with the TEK */ - key = PK11_UnwrapSymKey(Ks,CKM_SKIPJACK_WRAP, - NULL, &item, CKM_SKIPJACK_CBC64, CKA_DECRYPT, 0); - if (key == NULL) { - PK11_FreeSymKey(Ks); - return NULL; - } - - rv = PK11_WrapSymKey(CKM_SKIPJACK_WRAP, NULL, tek, key, &item); - PK11_FreeSymKey(Ks); - PK11_FreeSymKey(key); - if (rv != SECSuccess) { - return NULL; - } - - /* copy over our local serial number */ - PORT_Memset(header->u.fortezza.serial,0,sizeof(header->u.fortezza.serial)); - - /* change type to stream */ - PutInt2(header->type, PRE_FORTEZZA_STREAM); - - return(header); + PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); + return NULL; } diff --git a/security/nss/lib/ssl/ssl.h b/security/nss/lib/ssl/ssl.h index f6ab20af7..afd139d1c 100644 --- a/security/nss/lib/ssl/ssl.h +++ b/security/nss/lib/ssl/ssl.h @@ -110,6 +110,8 @@ SSL_IMPORT PRFileDesc *SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd); /* if step-down keys are needed. */ /* default: off, generate */ /* step-down keys if needed. */ +#define SSL_BYPASS_PKCS11 16 /* use PKCS#11 for pub key only */ +#define SSL_NO_LOCKS 17 /* Don't use locks for protection */ #ifdef SSL_DEPRECATED_FUNCTION /* Old deprecated function names */ @@ -171,6 +173,12 @@ SSL_IMPORT SECStatus SSL_ResetHandshake(PRFileDesc *fd, PRBool asServer); SSL_IMPORT SECStatus SSL_ForceHandshake(PRFileDesc *fd); /* +** Same as above, but with an I/O timeout. + */ +SSL_IMPORT SECStatus SSL_ForceHandshakeWithTimeout(PRFileDesc *fd, + PRIntervalTime timeout); + +/* ** Query security status of socket. *on is set to one if security is ** enabled. *keySize will contain the stream key size used. *issuer will ** contain the RFC1485 verison of the name of the issuer of the @@ -190,7 +198,7 @@ SSL_IMPORT SECStatus SSL_SecurityStatus(PRFileDesc *fd, int *on, char **cipher, #define SSL_SECURITY_STATUS_OFF 0 #define SSL_SECURITY_STATUS_ON_HIGH 1 #define SSL_SECURITY_STATUS_ON_LOW 2 -#define SSL_SECURITY_STATUS_FORTEZZA 3 +#define SSL_SECURITY_STATUS_FORTEZZA 3 /* NO LONGER SUPPORTED */ /* ** Return the certificate for our SSL peer. If the client calls this @@ -335,6 +343,14 @@ SSL_IMPORT SECStatus SSL_HandshakeCallback(PRFileDesc *fd, */ SSL_IMPORT SECStatus SSL_ReHandshake(PRFileDesc *fd, PRBool flushCache); +/* +** Same as above, but with an I/O timeout. + */ +SSL_IMPORT SECStatus SSL_ReHandshakeWithTimeout(PRFileDesc *fd, + PRBool flushCache, + PRIntervalTime timeout); + + #ifdef SSL_DEPRECATED_FUNCTION /* deprecated! ** For the server, request a new handshake. For the client, begin a new diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index 1e7f7411a..2b34b9519 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -62,6 +62,7 @@ #include "secmod.h" #include "nsslocks.h" #include "ec.h" +#include "blapi.h" #include <stdio.h> @@ -70,10 +71,11 @@ (x)->pValue=(v); (x)->ulValueLen = (l); #endif -static void ssl3_CleanupPeerCerts(ssl3State *ssl3); +static void ssl3_CleanupPeerCerts(sslSocket *ss); static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, PK11SlotInfo * serverKeySlot); -static SECStatus ssl3_GenerateSessionKeys(sslSocket *ss, const PK11SymKey *pms); +static SECStatus ssl3_DeriveMasterSecret(sslSocket *ss, const PK11SymKey *pms); +static SECStatus ssl3_DeriveConnectionKeysPKCS11(sslSocket *ss); static SECStatus ssl3_HandshakeFailure( sslSocket *ss); static SECStatus ssl3_InitState( sslSocket *ss); static sslSessionID *ssl3_NewSessionID( sslSocket *ss, PRBool is_server); @@ -109,7 +111,6 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = { #endif /* NSS_ENABLE_ECC */ { TLS_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, - { SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, #ifdef NSS_ENABLE_ECC { TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, { TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, @@ -136,7 +137,6 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = { { SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, { SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, - { SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, { SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, { SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, @@ -152,7 +152,6 @@ static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = { { SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, { SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, - { SSL_FORTEZZA_DMS_WITH_NULL_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, #ifdef NSS_ENABLE_ECC { TLS_ECDH_RSA_WITH_NULL_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, { TLS_ECDH_ECDSA_WITH_NULL_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, @@ -177,9 +176,6 @@ static const /*SSL3ClientCertificateType */ uint8 certificate_types [] = { #endif /* NSS_ENABLE_ECC */ }; -static const /*SSL3ClientCertificateType */ uint8 fortezza_certificate_types [] = { - ct_Fortezza, -}; /* * make sure there is room in the write buffer for padding and @@ -187,11 +183,6 @@ static const /*SSL3ClientCertificateType */ uint8 fortezza_certificate_types [] */ #define SSL3_BUFFER_FUDGE 100 -#define SET_ERROR_CODE /* reminder */ -#define SEND_ALERT /* reminder */ -#define TEST_FOR_FAILURE /* reminder */ -#define DEAL_WITH_FAILURE /* reminder */ - #define EXPORT_RSA_KEY_LENGTH 64 /* bytes */ @@ -217,13 +208,13 @@ static const ssl3BulkCipherDef bulk_cipher_defs[] = { {cipher_3des, calg_3des, 24, 24, type_block, 8, 8, kg_strong}, {cipher_des40, calg_des, 8, 5, type_block, 8, 8, kg_export}, {cipher_idea, calg_idea, 16, 16, type_block, 8, 8, kg_strong}, - {cipher_fortezza, calg_fortezza, 10, 10, type_block, 24, 8, kg_null}, {cipher_aes_128, calg_aes, 16, 16, type_block, 16,16, kg_strong}, {cipher_aes_256, calg_aes, 32, 32, type_block, 16,16, kg_strong}, {cipher_missing, calg_null, 0, 0, type_stream, 0, 0, kg_null}, }; -static const ssl3KEADef kea_defs[] = { /* indexed by SSL3KeyExchangeAlgorithm */ +static const ssl3KEADef kea_defs[] = +{ /* indexed by SSL3KeyExchangeAlgorithm */ /* kea exchKeyType signKeyType is_limited limit tls_keygen */ {kea_null, kt_null, sign_null, PR_FALSE, 0, PR_FALSE}, {kea_rsa, kt_rsa, sign_rsa, PR_FALSE, 0, PR_FALSE}, @@ -239,7 +230,6 @@ static const ssl3KEADef kea_defs[] = { /* indexed by SSL3KeyExchangeAlgorithm */ {kea_dhe_rsa_export, kt_dh, sign_rsa, PR_TRUE, 512, PR_FALSE}, {kea_dh_anon, kt_dh, sign_null, PR_FALSE, 0, PR_FALSE}, {kea_dh_anon_export, kt_dh, sign_null, PR_TRUE, 512, PR_FALSE}, - {kea_fortezza, kt_fortezza, sign_dsa, PR_FALSE, 0, PR_FALSE}, {kea_rsa_fips, kt_rsa, sign_rsa, PR_FALSE, 0, PR_TRUE }, #ifdef NSS_ENABLE_ECC {kea_ecdh_ecdsa, kt_ecdh, sign_ecdsa, PR_FALSE, 0, PR_FALSE}, @@ -250,7 +240,8 @@ static const ssl3KEADef kea_defs[] = { /* indexed by SSL3KeyExchangeAlgorithm */ }; /* must use ssl_LookupCipherSuiteDef to access */ -static const ssl3CipherSuiteDef cipher_suite_defs[] = { +static const ssl3CipherSuiteDef cipher_suite_defs[] = +{ /* cipher_suite bulk_cipher_alg mac_alg key_exchange_alg */ {SSL_NULL_WITH_NULL_NULL, cipher_null, mac_null, kea_null}, @@ -298,10 +289,6 @@ static const ssl3CipherSuiteDef cipher_suite_defs[] = { {SSL_DH_ANON_3DES_CBC_SHA, cipher_3des, mac_sha, kea_dh_anon}, #endif - {SSL_FORTEZZA_DMS_WITH_NULL_SHA, cipher_null, mac_sha, kea_fortezza}, - {SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, - cipher_fortezza, mac_sha, kea_fortezza}, - {SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, cipher_rc4, mac_sha, kea_fortezza}, /* New TLS cipher suites */ {TLS_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, mac_sha, kea_rsa}, @@ -362,14 +349,16 @@ typedef struct SSLCipher2MechStr { CK_MECHANISM_TYPE cmech; } SSLCipher2Mech; +/* indexed by type SSLCipherAlgorithm */ static const SSLCipher2Mech alg2Mech[] = { + /* calg, cmech */ { calg_null , (CK_MECHANISM_TYPE)0x80000000L }, { calg_rc4 , CKM_RC4 }, { calg_rc2 , CKM_RC2_CBC }, { calg_des , CKM_DES_CBC }, { calg_3des , CKM_DES3_CBC }, { calg_idea , CKM_IDEA_CBC }, - { calg_fortezza , CKM_SKIPJACK_CBC64 }, + { calg_fortezza , CKM_SKIPJACK_CBC64 }, { calg_aes , CKM_AES_CBC }, /* { calg_init , (CK_MECHANISM_TYPE)0x7fffffffL } */ }; @@ -401,114 +390,11 @@ const char * const ssl3_cipherName[] = { "3DES-EDE-CBC", "DES-CBC-40", "IDEA-CBC", - "FORTEZZA", "AES-128", "AES-256", "missing" }; -#ifdef NSS_ENABLE_ECC -/* Types and names of elliptic curves used in TLS */ -typedef enum { ec_type_explicitPrime = 1, - ec_type_explicitChar2Curve, - ec_type_named -} ECType; - -typedef enum { ec_noName = 0, - ec_sect163k1, ec_sect163r1, ec_sect163r2, - ec_sect193r1, ec_sect193r2, ec_sect233k1, - ec_sect233r1, ec_sect239k1, ec_sect283k1, - ec_sect283r1, ec_sect409k1, ec_sect409r1, - ec_sect571k1, ec_sect571r1, ec_secp160k1, - ec_secp160r1, ec_secp160r2, ec_secp192k1, - ec_secp192r1, ec_secp224k1, ec_secp224r1, - ec_secp256k1, ec_secp256r1, ec_secp384r1, - ec_secp521r1, - ec_pastLastName -} ECName; - -#define supportedCurve(x) (((x) > ec_noName) && ((x) < ec_pastLastName)) - -/* Table containing OID tags for elliptic curves named in the - * ECC-TLS IETF draft. - */ -static const SECOidTag ecName2OIDTag[] = { - 0, - SEC_OID_SECG_EC_SECT163K1, /* 1 */ - SEC_OID_SECG_EC_SECT163R1, /* 2 */ - SEC_OID_SECG_EC_SECT163R2, /* 3 */ - SEC_OID_SECG_EC_SECT193R1, /* 4 */ - SEC_OID_SECG_EC_SECT193R2, /* 5 */ - SEC_OID_SECG_EC_SECT233K1, /* 6 */ - SEC_OID_SECG_EC_SECT233R1, /* 7 */ - SEC_OID_SECG_EC_SECT239K1, /* 8 */ - SEC_OID_SECG_EC_SECT283K1, /* 9 */ - SEC_OID_SECG_EC_SECT283R1, /* 10 */ - SEC_OID_SECG_EC_SECT409K1, /* 11 */ - SEC_OID_SECG_EC_SECT409R1, /* 12 */ - SEC_OID_SECG_EC_SECT571K1, /* 13 */ - SEC_OID_SECG_EC_SECT571R1, /* 14 */ - SEC_OID_SECG_EC_SECP160K1, /* 15 */ - SEC_OID_SECG_EC_SECP160R1, /* 16 */ - SEC_OID_SECG_EC_SECP160R2, /* 17 */ - SEC_OID_SECG_EC_SECP192K1, /* 18 */ - SEC_OID_SECG_EC_SECP192R1, /* 19 */ - SEC_OID_SECG_EC_SECP224K1, /* 20 */ - SEC_OID_SECG_EC_SECP224R1, /* 21 */ - SEC_OID_SECG_EC_SECP256K1, /* 22 */ - SEC_OID_SECG_EC_SECP256R1, /* 23 */ - SEC_OID_SECG_EC_SECP384R1, /* 24 */ - SEC_OID_SECG_EC_SECP521R1, /* 25 */ -}; - -static SECStatus -ecName2params(PRArenaPool * arena, ECName curve, SECKEYECParams * params) -{ - SECOidData *oidData = NULL; - - if ((curve <= ec_noName) || (curve >= ec_pastLastName) || - ((oidData = SECOID_FindOIDByTag(ecName2OIDTag[curve])) == NULL)) { - PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); - return SECFailure; - } - - SECITEM_AllocItem(arena, params, (2 + oidData->oid.len)); - /* - * params->data needs to contain the ASN encoding of an object ID (OID) - * representing the named curve. The actual OID is in - * oidData->oid.data so we simply prepend 0x06 and OID length - */ - params->data[0] = SEC_ASN1_OBJECT_ID; - params->data[1] = oidData->oid.len; - memcpy(params->data + 2, oidData->oid.data, oidData->oid.len); - - return SECSuccess; -} - -static ECName -params2ecName(SECKEYECParams * params) -{ - SECItem oid = { siBuffer, NULL, 0}; - SECOidData *oidData = NULL; - ECName i; - - /* - * params->data needs to contain the ASN encoding of an object ID (OID) - * representing a named curve. Here, we strip away everything - * before the actual OID and use the OID to look up a named curve. - */ - if (params->data[0] != SEC_ASN1_OBJECT_ID) return ec_noName; - oid.len = params->len - 2; - oid.data = params->data + 2; - if ((oidData = SECOID_FindOID(&oid)) == NULL) return ec_noName; - for (i = ec_noName + 1; i < ec_pastLastName; i++) { - if (ecName2OIDTag[i] == oidData->offset) - return i; - } - - return ec_noName; -} -#endif /* NSS_ENABLE_ECC */ #if defined(TRACE) @@ -618,7 +504,7 @@ ssl3_config_match_init(sslSocket *ss) PRBool isServer; sslServerCerts *svrAuth; - if (!ss->enableSSL3 && !ss->enableTLS) { + if (!ss->opt.enableSSL3 && !ss->opt.enableTLS) { return 0; } isServer = (PRBool)( ss && ss->sec.isServer ); @@ -671,7 +557,8 @@ ssl3_config_match_init(sslSocket *ss) /* Mark the suites that are backed by real tokens, certs and keys */ suite->isPresent = (PRBool) (((exchKeyType == kt_null) || - ((!isServer || (svrAuth->serverKey && + ((!isServer || (svrAuth->serverKeyPair && + svrAuth->SERVERKEY && svrAuth->serverCertChain)) && PK11_TokenExists(kea_alg_defs[exchKeyType]))) && ((cipher_alg == calg_null) || PK11_TokenExists(cipher_mech))); @@ -713,7 +600,7 @@ count_cipher_suites(sslSocket *ss, int policy, PRBool enabled) { int i, count = 0; - if (!ss->enableSSL3 && !ss->enableTLS) { + if (!ss->opt.enableSSL3 && !ss->opt.enableTLS) { return 0; } for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) { @@ -731,7 +618,7 @@ anyRestrictedEnabled(sslSocket *ss) { int i; - if (!ss->enableSSL3 && !ss->enableTLS) { + if (!ss->opt.enableSSL3 && !ss->opt.enableTLS) { return PR_FALSE; } for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) { @@ -758,7 +645,6 @@ Null_Cipher(void *ctx, unsigned char *output, int *outputLen, int maxOutputLen, return SECSuccess; } - /* * SSL3 Utility functions */ @@ -769,21 +655,21 @@ ssl3_NegotiateVersion(sslSocket *ss, SSL3ProtocolVersion peerVersion) SSL3ProtocolVersion version; SSL3ProtocolVersion maxVersion; - if (ss->enableTLS) { + if (ss->opt.enableTLS) { maxVersion = SSL_LIBRARY_VERSION_3_1_TLS; - } else if (ss->enableSSL3) { + } else if (ss->opt.enableSSL3) { maxVersion = SSL_LIBRARY_VERSION_3_0; } else { /* what are we doing here? */ - PORT_Assert(ss->enableSSL3 || ss->enableTLS); + PORT_Assert(ss->opt.enableSSL3 || ss->opt.enableTLS); PORT_SetError(SSL_ERROR_SSL_DISABLED); return SECFailure; } ss->version = version = PR_MIN(maxVersion, peerVersion); - if ((version == SSL_LIBRARY_VERSION_3_1_TLS && ss->enableTLS) || - (version == SSL_LIBRARY_VERSION_3_0 && ss->enableSSL3)) { + if ((version == SSL_LIBRARY_VERSION_3_1_TLS && ss->opt.enableTLS) || + (version == SSL_LIBRARY_VERSION_3_0 && ss->opt.enableSSL3)) { return SECSuccess; } @@ -811,7 +697,8 @@ ssl3_GetNewRandom(SSL3Random *random) return rv; } -static SECStatus +/* Called by ssl3_SendServerKeyExchange and ssl3_SendCertificateVerify */ +SECStatus ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key, SECItem *buf, PRBool isTLS) { @@ -838,7 +725,6 @@ ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key, SECItem *buf, hashItem.len = sizeof(SSL3Hashes); break; case dsaKey: - case fortezzaKey: doDerEncode = isTLS; hashItem.data = hash->sha; hashItem.len = sizeof(hash->sha); @@ -881,8 +767,8 @@ done: return rv; } - -static SECStatus +/* Called from ssl3_HandleServerKeyExchange, ssl3_HandleCertificateVerify */ +SECStatus ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert, SECItem *buf, PRBool isTLS, void *pwArg) { @@ -911,7 +797,6 @@ ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert, hashItem.len = sizeof(SSL3Hashes); break; case dsaKey: - case fortezzaKey: hashItem.data = hash->sha; hashItem.len = sizeof(hash->sha); if (isTLS) { @@ -970,17 +855,49 @@ ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert, /* Caller must set hiLevel error code. */ +/* Called from ssl3_ComputeExportRSAKeyHash + * ssl3_ComputeDHKeyHash + * which are called from ssl3_HandleServerKeyExchange. + */ +SECStatus +ssl3_ComputeCommonKeyHash(PRUint8 * hashBuf, unsigned int bufLen, + SSL3Hashes *hashes, PRBool bypassPKCS11) +{ + SECStatus rv = SECSuccess; + + if (bypassPKCS11) { + MD5_HashBuf (hashes->md5, hashBuf, bufLen); + SHA1_HashBuf(hashes->sha, hashBuf, bufLen); + } else { + rv = PK11_HashBuf(SEC_OID_MD5, hashes->md5, hashBuf, bufLen); + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); + rv = SECFailure; + goto done; + } + + rv = PK11_HashBuf(SEC_OID_SHA1, hashes->sha, hashBuf, bufLen); + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); + rv = SECFailure; + } + } +done: + return rv; +} + +/* Caller must set hiLevel error code. +** Called from ssl3_SendServerKeyExchange and +** ssl3_HandleServerKeyExchange. +*/ static SECStatus ssl3_ComputeExportRSAKeyHash(SECItem modulus, SECItem publicExponent, SSL3Random *client_rand, SSL3Random *server_rand, - SSL3Hashes *hashes) + SSL3Hashes *hashes, PRBool bypassPKCS11) { - PK11Context * md5 = NULL; - PK11Context * sha = NULL; PRUint8 * hashBuf; PRUint8 * pBuf; SECStatus rv = SECSuccess; - unsigned int outLen; unsigned int bufLen; PRUint8 buf[2*SSL3_RANDOM_LENGTH + 2 + 4096/8 + 2 + 4096/8]; @@ -994,19 +911,6 @@ ssl3_ComputeExportRSAKeyHash(SECItem modulus, SECItem publicExponent, } } - md5 = PK11_CreateDigestContext(SEC_OID_MD5); - if (md5 == NULL) { - ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); - rv = SECFailure; /* Caller must set hiLevel error code. */ - goto done; - } - sha = PK11_CreateDigestContext(SEC_OID_SHA1); - if (sha == NULL) { - ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); - rv = SECFailure; /* Caller must set hiLevel error code. */ - goto done; - } - memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH); pBuf = hashBuf + SSL3_RANDOM_LENGTH; memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH); @@ -1023,50 +927,27 @@ ssl3_ComputeExportRSAKeyHash(SECItem modulus, SECItem publicExponent, pBuf += publicExponent.len; PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen); - rv = PK11_DigestBegin(md5); - rv |= PK11_DigestOp(md5, hashBuf, bufLen); - rv |= PK11_DigestFinal(md5, hashes->md5, &outLen, MD5_LENGTH); - PORT_Assert(rv != SECSuccess || outLen == MD5_LENGTH); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); - rv = SECFailure; - goto done; - } - - rv = PK11_DigestBegin(sha); - rv |= PK11_DigestOp(sha, hashBuf, bufLen); - rv |= PK11_DigestFinal(sha, hashes->sha, &outLen, SHA1_LENGTH); - PORT_Assert(rv != SECSuccess || outLen == SHA1_LENGTH); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); - rv = SECFailure; - goto done; - } + rv = ssl3_ComputeCommonKeyHash(hashBuf, bufLen, hashes, bypassPKCS11); PRINT_BUF(95, (NULL, "RSAkey hash: ", hashBuf, bufLen)); PRINT_BUF(95, (NULL, "RSAkey hash: MD5 result", hashes->md5, MD5_LENGTH)); PRINT_BUF(95, (NULL, "RSAkey hash: SHA1 result", hashes->sha, SHA1_LENGTH)); -done: - if (md5 != NULL) PK11_DestroyContext(md5, PR_TRUE); - if (sha != NULL) PK11_DestroyContext(sha, PR_TRUE); if (hashBuf != buf && hashBuf != NULL) PORT_Free(hashBuf); return rv; } /* Caller must set hiLevel error code. */ +/* Called from ssl3_HandleServerKeyExchange. */ static SECStatus ssl3_ComputeDHKeyHash(SECItem dh_p, SECItem dh_g, SECItem dh_Ys, SSL3Random *client_rand, SSL3Random *server_rand, - SSL3Hashes *hashes) + SSL3Hashes *hashes, PRBool bypassPKCS11) { - PK11Context * md5 = NULL; - PK11Context * sha = NULL; PRUint8 * hashBuf; PRUint8 * pBuf; SECStatus rv = SECSuccess; - unsigned int outLen; unsigned int bufLen; PRUint8 buf[2*SSL3_RANDOM_LENGTH + 2 + 4096/8 + 2 + 4096/8]; @@ -1080,19 +961,6 @@ ssl3_ComputeDHKeyHash(SECItem dh_p, SECItem dh_g, SECItem dh_Ys, } } - md5 = PK11_CreateDigestContext(SEC_OID_MD5); - if (md5 == NULL) { - ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); - rv = SECFailure; /* Caller must set hiLevel error code. */ - goto done; - } - sha = PK11_CreateDigestContext(SEC_OID_SHA1); - if (sha == NULL) { - ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); - rv = SECFailure; /* Caller must set hiLevel error code. */ - goto done; - } - memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH); pBuf = hashBuf + SSL3_RANDOM_LENGTH; memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH); @@ -1114,129 +982,17 @@ ssl3_ComputeDHKeyHash(SECItem dh_p, SECItem dh_g, SECItem dh_Ys, pBuf += dh_Ys.len; PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen); - rv = PK11_DigestBegin(md5); - rv |= PK11_DigestOp(md5, hashBuf, bufLen); - rv |= PK11_DigestFinal(md5, hashes->md5, &outLen, MD5_LENGTH); - PORT_Assert(rv != SECSuccess || outLen == MD5_LENGTH); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); - rv = SECFailure; - goto done; - } - - rv = PK11_DigestBegin(sha); - rv |= PK11_DigestOp(sha, hashBuf, bufLen); - rv |= PK11_DigestFinal(sha, hashes->sha, &outLen, SHA1_LENGTH); - PORT_Assert(rv != SECSuccess || outLen == SHA1_LENGTH); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); - rv = SECFailure; - goto done; - } + rv = ssl3_ComputeCommonKeyHash(hashBuf, bufLen, hashes, bypassPKCS11); PRINT_BUF(95, (NULL, "DHkey hash: ", hashBuf, bufLen)); PRINT_BUF(95, (NULL, "DHkey hash: MD5 result", hashes->md5, MD5_LENGTH)); PRINT_BUF(95, (NULL, "DHkey hash: SHA1 result", hashes->sha, SHA1_LENGTH)); -done: - if (md5 != NULL) PK11_DestroyContext(md5, PR_TRUE); - if (sha != NULL) PK11_DestroyContext(sha, PR_TRUE); if (hashBuf != buf && hashBuf != NULL) PORT_Free(hashBuf); return rv; } -#ifdef NSS_ENABLE_ECC -/* Caller must set hiLevel error code. */ -static SECStatus -ssl3_ComputeECDHKeyHash(SECItem ec_params, SECItem server_ecpoint, - SSL3Random *client_rand, SSL3Random *server_rand, - SSL3Hashes *hashes) -{ - PRUint8 * hashBuf; - PRUint8 * pBuf; - SECStatus rv = SECSuccess; - unsigned int bufLen; - /* - * XXX For now, we only support named curves (the appropriate - * checks are made before this method is called) so ec_params - * takes up only two bytes. ECPoint needs to fit in 256 bytes - * (because the spec says the length must fit in one byte) - */ - PRUint8 buf[2*SSL3_RANDOM_LENGTH + 2 + 1 + 256]; - - bufLen = 2*SSL3_RANDOM_LENGTH + ec_params.len + 1 + server_ecpoint.len; - if (bufLen <= sizeof buf) { - hashBuf = buf; - } else { - hashBuf = PORT_Alloc(bufLen); - if (!hashBuf) { - return SECFailure; - } - } - - memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH); - pBuf = hashBuf + SSL3_RANDOM_LENGTH; - memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH); - pBuf += SSL3_RANDOM_LENGTH; - memcpy(pBuf, ec_params.data, ec_params.len); - pBuf += ec_params.len; - pBuf[0] = (PRUint8)(server_ecpoint.len); - pBuf += 1; - memcpy(pBuf, server_ecpoint.data, server_ecpoint.len); - pBuf += server_ecpoint.len; - PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen); - - rv = PK11_HashBuf(SEC_OID_MD5, hashes->md5, hashBuf, bufLen); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); - rv = SECFailure; - goto done; - } - - rv = PK11_HashBuf(SEC_OID_SHA1, hashes->sha, hashBuf, bufLen); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); - rv = SECFailure; - goto done; - } - - PRINT_BUF(95, (NULL, "ECDHkey hash: ", hashBuf, bufLen)); - PRINT_BUF(95, (NULL, "ECDHkey hash: MD5 result", hashes->md5, MD5_LENGTH)); - PRINT_BUF(95, (NULL, "ECDHkey hash: SHA1 result", hashes->sha, SHA1_LENGTH)); - -done: - if (hashBuf != buf && hashBuf != NULL) - PORT_Free(hashBuf); - return rv; -} -#endif /* NSS_ENABLE_ECC */ - -/* Caller must set hiLevel error code. */ -static SECStatus -ssl3_ComputeFortezzaPublicKeyHash(SECItem publicValue, unsigned char * hash) -{ - PK11Context *sha = NULL; - SECStatus rv = SECFailure; - unsigned int outLen; - - sha = PK11_CreateDigestContext(SEC_OID_SHA1); - if (sha == NULL) { - return rv; /* Caller must set hiLevel error code. */ - } - - rv = PK11_DigestBegin(sha); - rv |= PK11_DigestOp(sha, (unsigned char *)publicValue.data, publicValue.len); - rv |= PK11_DigestFinal(sha, hash, &outLen, SHA1_LENGTH); - PORT_Assert(rv != SECSuccess || outLen == SHA1_LENGTH); - if (rv != SECSuccess) - rv = SECFailure; - PK11_DestroyContext(sha, PR_TRUE); - - return rv; -} - - static void ssl3_BumpSequenceNumber(SSL3SequenceNumber *num) { @@ -1245,7 +1001,7 @@ ssl3_BumpSequenceNumber(SSL3SequenceNumber *num) num->high++; } -/* Called only from ssl3_DestroyCipherSpec (immediately below). */ +/* Called twice, only from ssl3_DestroyCipherSpec (immediately below). */ static void ssl3_CleanupKeyMaterial(ssl3KeyMaterial *mat) { @@ -1263,18 +1019,19 @@ ssl3_CleanupKeyMaterial(ssl3KeyMaterial *mat) } } -/* Called from ssl3_SendChangeCipherSpecs() and ssl3_HandleChangeCipherSpecs() +/* Called from ssl3_SendChangeCipherSpecs() and +** ssl3_HandleChangeCipherSpecs() +** ssl3_DestroySSL3Info ** Caller must hold SpecWriteLock. */ static void ssl3_DestroyCipherSpec(ssl3CipherSpec *spec) { - -/* PORT_Assert( ssl_HaveSpecWriteLock(ss)); Don't have ss! */ - + PRBool freeit = (PRBool)(!spec->bypassCiphers); +/* PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); Don't have ss! */ if (spec->destroy) { - spec->destroy(spec->encodeContext,PR_TRUE); - spec->destroy(spec->decodeContext,PR_TRUE); + spec->destroy(spec->encodeContext, freeit); + spec->destroy(spec->decodeContext, freeit); spec->encodeContext = NULL; /* paranoia */ spec->decodeContext = NULL; } @@ -1282,36 +1039,41 @@ ssl3_DestroyCipherSpec(ssl3CipherSpec *spec) PK11_FreeSymKey(spec->master_secret); spec->master_secret = NULL; } + spec->msItem.data = NULL; + spec->msItem.len = 0; ssl3_CleanupKeyMaterial(&spec->client); ssl3_CleanupKeyMaterial(&spec->server); + spec->bypassCiphers = PR_FALSE; spec->destroy=NULL; } -/* Called from ssl3_HandleServerHello(), ssl3_SendServerHello() +/* Fill in the pending cipher spec with info from the selected ciphersuite. +** This is as much initialization as we can do without having key material. +** Called from ssl3_HandleServerHello(), ssl3_SendServerHello() ** Caller must hold the ssl3 handshake lock. ** Acquires & releases SpecWriteLock. */ static SECStatus -ssl3_SetupPendingCipherSpec(sslSocket *ss, ssl3State *ssl3) +ssl3_SetupPendingCipherSpec(sslSocket *ss) { ssl3CipherSpec * pwSpec; ssl3CipherSpec * cwSpec; - ssl3CipherSuite suite = ssl3->hs.cipher_suite; + ssl3CipherSuite suite = ss->ssl3.hs.cipher_suite; SSL3MACAlgorithm mac; SSL3BulkCipher cipher; SSL3KeyExchangeAlgorithm kea; const ssl3CipherSuiteDef *suite_def; PRBool isTLS; - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); ssl_GetSpecWriteLock(ss); /*******************************/ - pwSpec = ssl3->pwSpec; - PORT_Assert(pwSpec == ssl3->prSpec); + pwSpec = ss->ssl3.pwSpec; + PORT_Assert(pwSpec == ss->ssl3.prSpec); /* This hack provides maximal interoperability with SSL 3 servers. */ - cwSpec = ss->ssl3->cwSpec; + cwSpec = ss->ssl3.cwSpec; if (cwSpec->mac_def->mac == mac_null) { /* SSL records are not being MACed. */ cwSpec->version = ss->version; @@ -1336,9 +1098,9 @@ ssl3_SetupPendingCipherSpec(sslSocket *ss, ssl3State *ssl3) if (isTLS) mac += 2; - ssl3->hs.suite_def = suite_def; - ssl3->hs.kea_def = &kea_defs[kea]; - PORT_Assert(ssl3->hs.kea_def->kea == kea); + ss->ssl3.hs.suite_def = suite_def; + ss->ssl3.hs.kea_def = &kea_defs[kea]; + PORT_Assert(ss->ssl3.hs.kea_def->kea == kea); pwSpec->cipher_def = &bulk_cipher_defs[cipher]; PORT_Assert(pwSpec->cipher_def->cipher == cipher); @@ -1346,7 +1108,6 @@ ssl3_SetupPendingCipherSpec(sslSocket *ss, ssl3State *ssl3) pwSpec->mac_def = &mac_defs[mac]; PORT_Assert(pwSpec->mac_def->mac == mac); - ss->sec.keyBits = pwSpec->cipher_def->key_size * BPB; ss->sec.secretKeyBits = pwSpec->cipher_def->secret_key_size * BPB; ss->sec.cipherType = cipher; @@ -1360,83 +1121,233 @@ ssl3_SetupPendingCipherSpec(sslSocket *ss, ssl3State *ssl3) return SECSuccess; } -/* - * Called from: ssl3_SendClientKeyExchange (for Full handshake) - * ssl3_HandleClientKeyExchange (for Full handshake) - * ssl3_HandleServerHello (for session restart) - * ssl3_HandleClientHello (for session restart) - * Sets error code, but caller probably should override to disambiguate. - * NULL pms means re-use old master_secret. +/* Initialize encryption and MAC contexts for pending spec. + * Master Secret already is derived in spec->msItem + * Caller holds Spec write lock. */ static SECStatus -ssl3_InitPendingCipherSpec(sslSocket *ss, PK11SymKey *pms) +ssl3_InitPendingContextsBypass(sslSocket *ss) { ssl3CipherSpec * pwSpec; const ssl3BulkCipherDef *cipher_def; - PK11Context * serverContext = NULL; - PK11Context * clientContext = NULL; - SECItem * param; + void * serverContext = NULL; + void * clientContext = NULL; + BLapiInitContextFunc initFn = (BLapiInitContextFunc)NULL; + int mode = 0; + unsigned int optArg1 = 0; + unsigned int optArg2 = 0; + PRBool server_encrypts = ss->sec.isServer; CK_ULONG macLength; SSLCipherAlgorithm calg; SECStatus rv; + + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); + + PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); + + pwSpec = ss->ssl3.pwSpec; + cipher_def = pwSpec->cipher_def; + macLength = pwSpec->mac_size; + + /* MAC setup is done when computing the mac, not here. + * Now setup the crypto contexts. + */ + + calg = cipher_def->calg; + + serverContext = pwSpec->server.cipher_context; + clientContext = pwSpec->client.cipher_context; + + switch (calg) { + case ssl_calg_null: + pwSpec->encode = Null_Cipher; + pwSpec->decode = Null_Cipher; + pwSpec->destroy = NULL; + goto success; + + case ssl_calg_rc4: + initFn = (BLapiInitContextFunc)RC4_InitContext; + pwSpec->encode = (SSLCipher) RC4_Encrypt; + pwSpec->decode = (SSLCipher) RC4_Decrypt; + pwSpec->destroy = (SSLDestroy) RC4_DestroyContext; + break; + case ssl_calg_rc2: + initFn = (BLapiInitContextFunc)RC2_InitContext; + mode = NSS_RC2_CBC; + optArg1 = cipher_def->key_size; + pwSpec->encode = (SSLCipher) RC2_Encrypt; + pwSpec->decode = (SSLCipher) RC2_Decrypt; + pwSpec->destroy = (SSLDestroy) RC2_DestroyContext; + break; + case ssl_calg_des: + initFn = (BLapiInitContextFunc)DES_InitContext; + mode = NSS_DES_CBC; + optArg1 = server_encrypts; + pwSpec->encode = (SSLCipher) DES_Encrypt; + pwSpec->decode = (SSLCipher) DES_Decrypt; + pwSpec->destroy = (SSLDestroy) DES_DestroyContext; + break; + case ssl_calg_3des: + initFn = (BLapiInitContextFunc)DES_InitContext; + mode = NSS_DES_EDE3_CBC; + optArg1 = server_encrypts; + pwSpec->encode = (SSLCipher) DES_Encrypt; + pwSpec->decode = (SSLCipher) DES_Decrypt; + pwSpec->destroy = (SSLDestroy) DES_DestroyContext; + break; + case ssl_calg_aes: + initFn = (BLapiInitContextFunc)AES_InitContext; + mode = NSS_AES_CBC; + optArg1 = server_encrypts; + optArg2 = AES_BLOCK_SIZE; + pwSpec->encode = (SSLCipher) AES_Encrypt; + pwSpec->decode = (SSLCipher) AES_Decrypt; + pwSpec->destroy = (SSLDestroy) AES_DestroyContext; + break; + + case ssl_calg_idea: + case ssl_calg_fortezza : + default: + PORT_Assert(0); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + goto bail_out; + } + rv = (*initFn)(serverContext, + pwSpec->server.write_key_item.data, + pwSpec->server.write_key_item.len, + pwSpec->server.write_iv_item.data, + mode, optArg1, optArg2); + if (rv != SECSuccess) { + PORT_Assert(0); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + goto bail_out; + } + + if (calg == ssl_calg_des || calg == ssl_calg_3des || calg == ssl_calg_aes) { + /* For block ciphers, if the server is encrypting, then the client + * is decrypting, and vice versa. + */ + optArg1 = !optArg1; + } + + rv = (*initFn)(clientContext, + pwSpec->client.write_key_item.data, + pwSpec->client.write_key_item.len, + pwSpec->client.write_iv_item.data, + mode, optArg1, optArg2); + if (rv != SECSuccess) { + PORT_Assert(0); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + goto bail_out; + } + + pwSpec->encodeContext = (ss->sec.isServer) ? serverContext : clientContext; + pwSpec->decodeContext = (ss->sec.isServer) ? clientContext : serverContext; + +success: + return SECSuccess; + +bail_out: + return SECFailure; +} + +/* This function should probably be moved to pk11wrap and be named + * PK11_ParamFromIVAndEffectiveKeyBits + */ +static SECItem * +ssl3_ParamFromIV(CK_MECHANISM_TYPE mtype, SECItem *iv, CK_ULONG ulEffectiveBits) +{ + SECItem * param = PK11_ParamFromIV(mtype, iv); + if (param && param->data && param->len >= sizeof(CK_RC2_PARAMS)) { + switch (mtype) { + case CKM_RC2_KEY_GEN: + case CKM_RC2_ECB: + case CKM_RC2_CBC: + case CKM_RC2_MAC: + case CKM_RC2_MAC_GENERAL: + case CKM_RC2_CBC_PAD: + *(CK_RC2_PARAMS *)param->data = ulEffectiveBits; + default: break; + } + } + return param; +} + +/* Initialize encryption and MAC contexts for pending spec. + * Master Secret already is derived. + * Caller holds Spec write lock. + */ +static SECStatus +ssl3_InitPendingContextsPKCS11(sslSocket *ss) +{ + ssl3CipherSpec * pwSpec; +const ssl3BulkCipherDef *cipher_def; + PK11Context * serverContext = NULL; + PK11Context * clientContext = NULL; + SECItem * param; CK_MECHANISM_TYPE mechanism; CK_MECHANISM_TYPE mac_mech; + CK_ULONG macLength; + CK_ULONG effKeyBits; SECItem iv; SECItem mac_param; + SSLCipherAlgorithm calg; - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); - ssl_GetSpecWriteLock(ss); /**************************************/ + PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); - PORT_Assert(ss->ssl3->prSpec == ss->ssl3->pwSpec); - - pwSpec = ss->ssl3->pwSpec; + pwSpec = ss->ssl3.pwSpec; cipher_def = pwSpec->cipher_def; macLength = pwSpec->mac_size; - /* generate session keys from pms (if pms is not NULL) or ms */ - rv = ssl3_GenerateSessionKeys(ss, pms); - if (rv != SECSuccess) { - goto bail_out; /* err code set by ssl3_GenerateSessionKeys */ - } + /* + ** Now setup the MAC contexts, + ** crypto contexts are setup below. + */ pwSpec->client.write_mac_context = NULL; pwSpec->server.write_mac_context = NULL; - + mac_mech = pwSpec->mac_def->mmech; mac_param.data = (unsigned char *)&macLength; mac_param.len = sizeof(macLength); mac_param.type = 0; - mac_mech = pwSpec->mac_def->mmech; - if (cipher_def->calg == calg_null) { - pwSpec->encode = Null_Cipher; - pwSpec->decode = Null_Cipher; - pwSpec->destroy = NULL; - pwSpec->client.write_mac_context = PK11_CreateContextBySymKey( - mac_mech, CKA_SIGN, pwSpec->client.write_mac_key, &mac_param); - if (pwSpec->client.write_mac_context == NULL) { - ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); - goto fail; - } - pwSpec->server.write_mac_context = PK11_CreateContextBySymKey( - mac_mech, CKA_SIGN, pwSpec->server.write_mac_key, &mac_param); - if (pwSpec->server.write_mac_context == NULL) { - ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); - goto fail; - } - goto success; + pwSpec->client.write_mac_context = PK11_CreateContextBySymKey( + mac_mech, CKA_SIGN, pwSpec->client.write_mac_key, &mac_param); + if (pwSpec->client.write_mac_context == NULL) { + ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); + goto fail; + } + pwSpec->server.write_mac_context = PK11_CreateContextBySymKey( + mac_mech, CKA_SIGN, pwSpec->server.write_mac_key, &mac_param); + if (pwSpec->server.write_mac_context == NULL) { + ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); + goto fail; } + /* + ** Now setup the crypto contexts. + */ + calg = cipher_def->calg; PORT_Assert(alg2Mech[calg].calg == calg); + + if (calg == calg_null) { + pwSpec->encode = Null_Cipher; + pwSpec->decode = Null_Cipher; + pwSpec->destroy = NULL; + return SECSuccess; + } mechanism = alg2Mech[calg].cmech; + effKeyBits = cipher_def->key_size * BPB; /* * build the server context */ iv.data = pwSpec->server.write_iv; iv.len = cipher_def->iv_size; - param = PK11_ParamFromIV(mechanism, &iv); + param = ssl3_ParamFromIV(mechanism, &iv, effKeyBits); if (param == NULL) { ssl_MapLowLevelError(SSL_ERROR_IV_PARAM_FAILURE); goto fail; @@ -1458,7 +1369,8 @@ const ssl3BulkCipherDef *cipher_def; */ iv.data = pwSpec->client.write_iv; iv.len = cipher_def->iv_size; - param = PK11_ParamFromIV(mechanism, &iv); + + param = ssl3_ParamFromIV(mechanism, &iv, effKeyBits); if (param == NULL) { ssl_MapLowLevelError(SSL_ERROR_IV_PARAM_FAILURE); goto fail; @@ -1474,30 +1386,16 @@ const ssl3BulkCipherDef *cipher_def; ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); goto fail; } - - pwSpec->encodeContext = (ss->sec.isServer) ? serverContext : clientContext; - pwSpec->decodeContext = (ss->sec.isServer) ? clientContext : serverContext; pwSpec->encode = (SSLCipher) PK11_CipherOp; pwSpec->decode = (SSLCipher) PK11_CipherOp; pwSpec->destroy = (SSLDestroy) PK11_DestroyContext; + pwSpec->encodeContext = (ss->sec.isServer) ? serverContext : clientContext; + pwSpec->decodeContext = (ss->sec.isServer) ? clientContext : serverContext; + serverContext = NULL; clientContext = NULL; - pwSpec->client.write_mac_context = PK11_CreateContextBySymKey( - mac_mech,CKA_SIGN, pwSpec->client.write_mac_key,&mac_param); - if (pwSpec->client.write_mac_context == NULL) { - ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); - goto fail; - } - pwSpec->server.write_mac_context = PK11_CreateContextBySymKey( - mac_mech, CKA_SIGN, pwSpec->server.write_mac_key,&mac_param); - if (pwSpec->server.write_mac_context == NULL) { - ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); - goto fail; - } -success: - ssl_ReleaseSpecWriteLock(ss); /******************************/ return SECSuccess; fail: @@ -1511,11 +1409,74 @@ fail: PK11_DestroyContext(pwSpec->server.write_mac_context,PR_TRUE); pwSpec->server.write_mac_context = NULL; } -bail_out: - ssl_ReleaseSpecWriteLock(ss); + return SECFailure; } +/* Complete the initialization of all keys, ciphers, MACs and their contexts + * for the pending Cipher Spec. + * Called from: ssl3_SendClientKeyExchange (for Full handshake) + * ssl3_HandleRSAClientKeyExchange (for Full handshake) + * ssl3_HandleServerHello (for session restart) + * ssl3_HandleClientHello (for session restart) + * Sets error code, but caller probably should override to disambiguate. + * NULL pms means re-use old master_secret. + * + * This code is common to the bypass and PKCS11 execution paths. + * For the bypass case, pms is NULL. + */ +SECStatus +ssl3_InitPendingCipherSpec(sslSocket *ss, PK11SymKey *pms) +{ + ssl3CipherSpec * pwSpec; + SECStatus rv; + + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); + + ssl_GetSpecWriteLock(ss); /**************************************/ + + PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); + + pwSpec = ss->ssl3.pwSpec; + + if (pms || (!pwSpec->msItem.len && !pwSpec->master_secret)) { + rv = ssl3_DeriveMasterSecret(ss, pms); + if (rv != SECSuccess) { + goto done; /* err code set by ssl3_DeriveMasterSecret */ + } + } + if (pwSpec->msItem.len && pwSpec->msItem.data) { + /* Double Bypass */ + const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def; + PRBool isTLS = (PRBool)(kea_def->tls_keygen || + (pwSpec->version > SSL_LIBRARY_VERSION_3_0)); + pwSpec->bypassCiphers = PR_TRUE; + rv = ssl3_KeyAndMacDeriveBypass( pwSpec, + (const unsigned char *)&ss->ssl3.hs.client_random, + (const unsigned char *)&ss->ssl3.hs.server_random, + isTLS, + (PRBool)(kea_def->is_limited)); + if (rv == SECSuccess) { + rv = ssl3_InitPendingContextsBypass(ss); + } + } else if (pwSpec->master_secret) { + rv = ssl3_DeriveConnectionKeysPKCS11(ss); + if (rv == SECSuccess) { + rv = ssl3_InitPendingContextsPKCS11(ss); + } + } else { + PORT_Assert(pwSpec->master_secret); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + rv = SECFailure; + } + +done: + ssl_ReleaseSpecWriteLock(ss); /******************************/ + if (rv != SECSuccess) + ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); + return rv; +} + /* * 60 bytes is 3 times the maximum length MAC size that is supported. */ @@ -1547,29 +1508,21 @@ static const unsigned char mac_pad_2 [60] = { static SECStatus ssl3_ComputeRecordMAC( ssl3CipherSpec * spec, - PK11Context * mac_context, + PRBool useServerMacKey, SSL3ContentType type, SSL3ProtocolVersion version, SSL3SequenceNumber seq_num, - SSL3Opaque * input, + const SSL3Opaque * input, int inputLength, unsigned char * outbuf, unsigned int * outLength) { const ssl3MACDef * mac_def; SECStatus rv; + PRBool isTLS; unsigned int tempLen; unsigned char temp[MAX_MAC_LENGTH]; -/* ssl_GetSpecReadLock(ss); Don't have "ss"! */ - - mac_def = spec->mac_def; - if (mac_def->mac == mac_null) { - *outLength = 0; -/* ssl_ReleaseSpecReadLock(ss); */ - return SECSuccess; - } - temp[0] = (unsigned char)(seq_num.high >> 24); temp[1] = (unsigned char)(seq_num.high >> 16); temp[2] = (unsigned char)(seq_num.high >> 8); @@ -1581,7 +1534,7 @@ ssl3_ComputeRecordMAC( temp[8] = type; /* TLS MAC includes the record's version field, SSL's doesn't. - ** We decide which MAC defintion to use based on the version of + ** We decide which MAC defintiion to use based on the version of ** the protocol that was negotiated when the spec became current, ** NOT based on the version value in the record itself. ** But, we use the record'v version value in the computation. @@ -1590,6 +1543,7 @@ ssl3_ComputeRecordMAC( temp[9] = MSB(inputLength); temp[10] = LSB(inputLength); tempLen = 11; + isTLS = PR_FALSE; } else { /* New TLS hash includes version. */ temp[9] = MSB(version); @@ -1597,20 +1551,112 @@ ssl3_ComputeRecordMAC( temp[11] = MSB(inputLength); temp[12] = LSB(inputLength); tempLen = 13; + isTLS = PR_TRUE; } PRINT_BUF(95, (NULL, "frag hash1: temp", temp, tempLen)); PRINT_BUF(95, (NULL, "frag hash1: input", input, inputLength)); - rv = PK11_DigestBegin(mac_context); - rv |= PK11_DigestOp(mac_context, temp, tempLen); - rv |= PK11_DigestOp(mac_context, input, inputLength); + mac_def = spec->mac_def; + if (mac_def->mac == mac_null) { + *outLength = 0; + return SECSuccess; + } + if (! spec->bypassCiphers) { + PK11Context *mac_context = + (useServerMacKey ? spec->server.write_mac_context + : spec->client.write_mac_context); + rv = PK11_DigestBegin(mac_context); + rv |= PK11_DigestOp(mac_context, temp, tempLen); + rv |= PK11_DigestOp(mac_context, input, inputLength); + rv |= PK11_DigestFinal(mac_context, outbuf, outLength, spec->mac_size); + } else { + /* bypass version */ + const SECHashObject *hashObj = NULL; + unsigned int pad_bytes; + PRUint64 write_mac_context[MAX_MAC_CONTEXT_LLONGS]; + + switch (mac_def->mac) { + case ssl_mac_null: + *outLength = 0; + return SECSuccess; + case ssl_mac_md5: + pad_bytes = 48; + hashObj = HASH_GetRawHashObject(HASH_AlgMD5); + break; + case ssl_mac_sha: + pad_bytes = 40; + hashObj = HASH_GetRawHashObject(HASH_AlgSHA1); + break; + case ssl_hmac_md5: /* used with TLS */ + hashObj = HASH_GetRawHashObject(HASH_AlgMD5); + break; + case ssl_hmac_sha: /* used with TLS */ + hashObj = HASH_GetRawHashObject(HASH_AlgSHA1); + break; + default: + break; + } + if (!hashObj) { + PORT_Assert(0); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + + if (!isTLS) { + /* compute "inner" part of SSL3 MAC */ + hashObj->begin(write_mac_context); + if (useServerMacKey) + hashObj->update(write_mac_context, + spec->server.write_mac_key_item.data, + spec->server.write_mac_key_item.len); + else + hashObj->update(write_mac_context, + spec->client.write_mac_key_item.data, + spec->client.write_mac_key_item.len); + hashObj->update(write_mac_context, mac_pad_1, pad_bytes); + hashObj->update(write_mac_context, temp, tempLen); + hashObj->update(write_mac_context, input, inputLength); + hashObj->end(write_mac_context, temp, &tempLen, sizeof temp); + + /* compute "outer" part of SSL3 MAC */ + hashObj->begin(write_mac_context); + if (useServerMacKey) + hashObj->update(write_mac_context, + spec->server.write_mac_key_item.data, + spec->server.write_mac_key_item.len); + else + hashObj->update(write_mac_context, + spec->client.write_mac_key_item.data, + spec->client.write_mac_key_item.len); + hashObj->update(write_mac_context, mac_pad_2, pad_bytes); + hashObj->update(write_mac_context, temp, tempLen); + hashObj->end(write_mac_context, outbuf, outLength, spec->mac_size); + rv = SECSuccess; + } else { /* is TLS */ +#define cx ((HMACContext *)write_mac_context) + if (useServerMacKey) { + rv = HMAC_Init(cx, hashObj, + spec->server.write_mac_key_item.data, + spec->server.write_mac_key_item.len, PR_FALSE); + } else { + rv = HMAC_Init(cx, hashObj, + spec->client.write_mac_key_item.data, + spec->client.write_mac_key_item.len, PR_FALSE); + } + if (rv == SECSuccess) { + HMAC_Begin(cx); + HMAC_Update(cx, temp, tempLen); + HMAC_Update(cx, input, inputLength); + rv = HMAC_Finish(cx, outbuf, outLength, spec->mac_size); + HMAC_Destroy(cx, PR_FALSE); + } +#undef cx + } + } - rv |= PK11_DigestFinal(mac_context, outbuf, outLength, spec->mac_size); PORT_Assert(rv != SECSuccess || *outLength == (unsigned)spec->mac_size); -/* ssl_ReleaseSpecReadLock(ss); */ - PRINT_BUF(95, (NULL, "frag hash2: result", outbuf, *outLength)); if (rv != SECSuccess) { @@ -1667,23 +1713,20 @@ ssl3_SendRecord( sslSocket * ss, SECStatus rv; PRUint32 bufSize = 0; PRInt32 sent = 0; - PRInt32 cipherBytes = -1; PRBool isBlocking = ssl_SocketIsBlocking(ss); - PRBool ssl3WasNull = PR_FALSE; SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s bytes=%d", SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type), bytes)); PRINT_BUF(3, (ss, "Send record (plain text)", buf, bytes)); - PORT_Assert( ssl_HaveXmitBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); - if (ss->ssl3 == NULL) { + if (ss->ssl3.initialized == PR_FALSE) { /* This can happen on a server if the very first incoming record ** looks like a defective ssl3 record (e.g. too long), and we're ** trying to send an alert. */ - ssl3WasNull = PR_TRUE; PR_ASSERT(type == content_alert); rv = ssl3_InitState(ss); if (rv != SECSuccess) { @@ -1702,6 +1745,8 @@ ssl3_SendRecord( sslSocket * ss, PRUint32 contentLen; PRUint32 fragLen; PRUint32 macLen; + PRInt32 cipherBytes = 0; + PRUint32 p1Len, p2Len, oddLen = 0; contentLen = PR_MIN(bytes, MAX_FRAGMENT_LENGTH); if (write->space < contentLen + SSL3_BUFFER_FUDGE) { @@ -1713,39 +1758,34 @@ ssl3_SendRecord( sslSocket * ss, } } - /* This variable records - * the actual size of the buffer we allocated above. Some - * algorithms (FORTEZZA) will expand the number of bytes it needs to - * send data. If we only supply the output buffer with the same number + /* This variable records the actual size of the buffer allocated above. + * Some algorithms may expand the number of bytes needed to send data. + * If we only supply the output buffer with the same number * of bytes as the input buffer, we will fail. */ bufSize = contentLen + SSL3_BUFFER_FUDGE; /* * null compression is easy to do - */ PORT_Memcpy(write->buf + SSL3_RECORD_HEADER_LENGTH, buf, contentLen); - buf += contentLen; - bytes -= contentLen; - PORT_Assert( bytes >= 0 ); + */ ssl_GetSpecReadLock(ss); /********************************/ - cwSpec = ss->ssl3->cwSpec; + cwSpec = ss->ssl3.cwSpec; cipher_def = cwSpec->cipher_def; /* * Add the MAC */ - rv = ssl3_ComputeRecordMAC( - cwSpec, (ss->sec.isServer) ? cwSpec->server.write_mac_context - : cwSpec->client.write_mac_context, - type, cwSpec->version, cwSpec->write_seq_num, - write->buf + SSL3_RECORD_HEADER_LENGTH, contentLen, + rv = ssl3_ComputeRecordMAC( cwSpec, (PRBool)(ss->sec.isServer), + type, cwSpec->version, cwSpec->write_seq_num, buf, contentLen, write->buf + contentLen + SSL3_RECORD_HEADER_LENGTH, &macLen); if (rv != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE); goto spec_locked_loser; } + p1Len = contentLen; + p2Len = macLen; fragLen = contentLen + macLen; /* needs to be encrypted */ PORT_Assert(fragLen <= MAX_FRAGMENT_LENGTH + 1024); @@ -1754,10 +1794,11 @@ ssl3_SendRecord( sslSocket * ss, * then Encrypt it */ if (cipher_def->type == type_block) { + unsigned char * pBuf; int padding_length; int i; - unsigned char * pBuf; + oddLen = contentLen % cipher_def->block_size; /* Assume blockSize is a power of two */ padding_length = cipher_def->block_size - 1 - ((fragLen) & (cipher_def->block_size - 1)); @@ -1769,11 +1810,49 @@ ssl3_SendRecord( sslSocket * ss, for (i = padding_length + 1; i > 0; --i) { *pBuf-- = padding_length; } + /* now, if contentLen is not a multiple of block size, fix it */ + p2Len = fragLen - p1Len; + } + if (p1Len < 256) { + oddLen = p1Len; + p1Len = 0; + } else { + p1Len -= oddLen; + } + if (oddLen) { + p2Len += oddLen; + PORT_Assert( (cipher_def->block_size < 2) || \ + (p2Len % cipher_def->block_size) == 0); + memcpy(write->buf + SSL3_RECORD_HEADER_LENGTH + p1Len, + buf + p1Len, oddLen); + } + if (p1Len > 0) { + rv = cwSpec->encode( cwSpec->encodeContext, + write->buf + SSL3_RECORD_HEADER_LENGTH, /* output */ + &cipherBytes, /* actual outlen */ + p1Len, /* max outlen */ + buf, p1Len); /* input, and inputlen */ + PORT_Assert(rv == SECSuccess && cipherBytes == p1Len); + if (rv != SECSuccess || cipherBytes != p1Len) { + PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); + goto spec_locked_loser; + } } - rv = cwSpec->encode( - cwSpec->encodeContext, write->buf + SSL3_RECORD_HEADER_LENGTH, - &cipherBytes, bufSize, write->buf + SSL3_RECORD_HEADER_LENGTH, - fragLen); + if (p2Len > 0) { + PRInt32 cipherBytesPart2 = -1; + rv = cwSpec->encode( cwSpec->encodeContext, + write->buf + SSL3_RECORD_HEADER_LENGTH + p1Len, + &cipherBytesPart2, /* output and actual outLen */ + p2Len, /* max outlen */ + write->buf + SSL3_RECORD_HEADER_LENGTH + p1Len, + p2Len); /* input and inputLen*/ + PORT_Assert(rv == SECSuccess && cipherBytesPart2 == p2Len); + if (rv != SECSuccess || cipherBytesPart2 != p2Len) { + PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); + goto spec_locked_loser; + } + cipherBytes += cipherBytesPart2; + } if (rv != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_ENCRYPTION_FAILURE); spec_locked_loser: @@ -1791,6 +1870,10 @@ spec_locked_loser: ssl_ReleaseSpecReadLock(ss); /************************************/ + buf += contentLen; + bytes -= contentLen; + PORT_Assert( bytes >= 0 ); + /* PORT_Assert(fragLen == cipherBytes); */ write->len = cipherBytes + SSL3_RECORD_HEADER_LENGTH; write->buf[0] = type; @@ -1870,7 +1953,7 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in, { PRInt32 sent = 0; - PORT_Assert( ssl_HaveXmitBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); while (len > 0) { PRInt32 count; @@ -1914,8 +1997,8 @@ ssl3_FlushHandshake(sslSocket *ss, PRInt32 flags) { PRInt32 rv; - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss)); - PORT_Assert( ssl_HaveXmitBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); if (!ss->sec.ci.sendBuf.buf || !ss->sec.ci.sendBuf.len) return SECSuccess; @@ -1946,7 +2029,7 @@ ssl3_HandleNoCertificate(sslSocket *ss) CERT_DestroyCertificate(ss->sec.peerCert); ss->sec.peerCert = NULL; } - ssl3_CleanupPeerCerts(ss->ssl3); + ssl3_CleanupPeerCerts(ss); /* If the server has required client-auth blindly but doesn't * actually look at the certificate it won't know that no @@ -1955,9 +2038,9 @@ ssl3_HandleNoCertificate(sslSocket *ss) * first handshake because if we're redoing the handshake we * know the server is paying attention to the certificate. */ - if ((ss->requireCertificate == SSL_REQUIRE_ALWAYS) || + if ((ss->opt.requireCertificate == SSL_REQUIRE_ALWAYS) || (!ss->firstHsDone && - (ss->requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE))) { + (ss->opt.requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE))) { PRFileDesc * lower; ss->sec.uncache(ss->sec.ci.sid); @@ -1994,7 +2077,6 @@ ssl3_HandleNoCertificate(sslSocket *ss) ** ssl3_HandleClientHello <- ** ssl3_HandleV2ClientHello <- ** ssl3_HandleCertificateVerify <- -** ssl3_HandleFortezzaClientKeyExchange <- ** ssl3_HandleClientKeyExchange <- ** ssl3_HandleCertificate <- ** ssl3_HandleFinished <- @@ -2042,7 +2124,7 @@ ssl3_IllegalParameter(sslSocket *ss) { PRBool isTLS; - isTLS = (PRBool)(ss->ssl3->pwSpec->version > SSL_LIBRARY_VERSION_3_0); + isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter); PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT : SSL_ERROR_BAD_SERVER ); @@ -2085,8 +2167,8 @@ ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf) SSL3AlertDescription desc; int error; - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); SSL_TRC(3, ("%d: SSL3[%d]: handle alert record", SSL_GETPID(), ss->fd)); @@ -2140,7 +2222,7 @@ ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf) } if (level == alert_fatal) { ss->sec.uncache(ss->sec.ci.sid); - if ((ss->ssl3->hs.ws == wait_server_hello) && + if ((ss->ssl3.hs.ws == wait_server_hello) && (desc == handshake_failure)) { /* XXX This is a hack. We're assuming that any handshake failure * XXX on the client hello is a failure to match ciphers. @@ -2150,12 +2232,12 @@ ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf) PORT_SetError(error); return SECFailure; } - if ((desc == no_certificate) && (ss->ssl3->hs.ws == wait_client_cert)) { + if ((desc == no_certificate) && (ss->ssl3.hs.ws == wait_client_cert)) { /* I'm a server. I've requested a client cert. He hasn't got one. */ SECStatus rv; PORT_Assert(ss->sec.isServer); - ss->ssl3->hs.ws = wait_client_key; + ss->ssl3.hs.ws = wait_client_key; rv = ssl3_HandleNoCertificate(ss); return rv; } @@ -2176,7 +2258,6 @@ static SECStatus ssl3_SendChangeCipherSpecs(sslSocket *ss) { uint8 change = change_cipher_spec_choice; - ssl3State * ssl3 = ss->ssl3; ssl3CipherSpec * pwSpec; SECStatus rv; PRInt32 sent; @@ -2184,8 +2265,8 @@ ssl3_SendChangeCipherSpecs(sslSocket *ss) SSL_TRC(3, ("%d: SSL3[%d]: send change_cipher_spec record", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveXmitBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER); if (rv != SECSuccess) { @@ -2199,12 +2280,12 @@ ssl3_SendChangeCipherSpecs(sslSocket *ss) /* swap the pending and current write specs. */ ssl_GetSpecWriteLock(ss); /**************************************/ - pwSpec = ss->ssl3->pwSpec; + pwSpec = ss->ssl3.pwSpec; pwSpec->write_seq_num.high = 0; pwSpec->write_seq_num.low = 0; - ssl3->pwSpec = ssl3->cwSpec; - ssl3->cwSpec = pwSpec; + ss->ssl3.pwSpec = ss->ssl3.cwSpec; + ss->ssl3.cwSpec = pwSpec; SSL_TRC(3, ("%d: SSL3[%d] Set Current Write Cipher Suite to Pending", SSL_GETPID(), ss->fd )); @@ -2213,8 +2294,8 @@ ssl3_SendChangeCipherSpecs(sslSocket *ss) /* If we are really through with the old cipher spec * (Both the read and write sides have changed) destroy it. */ - if (ss->ssl3->prSpec == ss->ssl3->pwSpec) { - ssl3_DestroyCipherSpec(ss->ssl3->pwSpec); + if (ss->ssl3.prSpec == ss->ssl3.pwSpec) { + ssl3_DestroyCipherSpec(ss->ssl3.pwSpec); } ssl_ReleaseSpecWriteLock(ss); /**************************************/ @@ -2231,11 +2312,11 @@ static SECStatus ssl3_HandleChangeCipherSpecs(sslSocket *ss, sslBuffer *buf) { ssl3CipherSpec * prSpec; - SSL3WaitState ws = ss->ssl3->hs.ws; + SSL3WaitState ws = ss->ssl3.hs.ws; SSL3ChangeCipherSpecChoice change; - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); SSL_TRC(3, ("%d: SSL3[%d]: handle change_cipher_spec record", SSL_GETPID(), ss->fd)); @@ -2262,12 +2343,12 @@ ssl3_HandleChangeCipherSpecs(sslSocket *ss, sslBuffer *buf) /* Swap the pending and current read specs. */ ssl_GetSpecWriteLock(ss); /*************************************/ - prSpec = ss->ssl3->prSpec; + prSpec = ss->ssl3.prSpec; prSpec->read_seq_num.high = prSpec->read_seq_num.low = 0; - ss->ssl3->prSpec = ss->ssl3->crSpec; - ss->ssl3->crSpec = prSpec; - ss->ssl3->hs.ws = wait_finished; + ss->ssl3.prSpec = ss->ssl3.crSpec; + ss->ssl3.crSpec = prSpec; + ss->ssl3.hs.ws = wait_finished; SSL_TRC(3, ("%d: SSL3[%d] Set Current Read Cipher Suite to Pending", SSL_GETPID(), ss->fd )); @@ -2275,65 +2356,45 @@ ssl3_HandleChangeCipherSpecs(sslSocket *ss, sslBuffer *buf) /* If we are really through with the old cipher prSpec * (Both the read and write sides have changed) destroy it. */ - if (ss->ssl3->prSpec == ss->ssl3->pwSpec) { - ssl3_DestroyCipherSpec(ss->ssl3->prSpec); + if (ss->ssl3.prSpec == ss->ssl3.pwSpec) { + ssl3_DestroyCipherSpec(ss->ssl3.prSpec); } ssl_ReleaseSpecWriteLock(ss); /*************************************/ return SECSuccess; } -/* - * Key generation given pre master secret, or master secret (if !pms). - * Sets a useful error code when returning SECFailure. - * - * Called only from ssl3_InitPendingCipherSpec(), - * - * which in turn is called from - * ssl3_SendClientKeyExchange (for Full handshake) - * ssl3_HandleClientKeyExchange (for Full handshake) - * ssl3_HandleServerHello (for session restart) - * ssl3_HandleClientHello (for session restart) - * Caller MUST hold the specWriteLock, and SSL3HandshakeLock. - * ssl3_InitPendingCipherSpec does that. - */ +/* This method uses PKCS11 to derive the MS from the PMS, where PMS +** is a PKCS11 symkey. This is used in all cases except the +** "triple bypass" with RSA key exchange. +** Called from ssl3_InitPendingCipherSpec. prSpec is pwSpec. +*/ static SECStatus -ssl3_GenerateSessionKeys(sslSocket *ss, const PK11SymKey *pms) +ssl3_DeriveMasterSecret(sslSocket *ss, const PK11SymKey *pms) { - ssl3CipherSpec * pwSpec = ss->ssl3->pwSpec; - const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def; - const ssl3KEADef * kea_def = ss->ssl3->hs.kea_def; - unsigned char * cr = (unsigned char *)&ss->ssl3->hs.client_random; - unsigned char * sr = (unsigned char *)&ss->ssl3->hs.server_random; - PK11SymKey * symKey = NULL; - PK11SlotInfo * slot = NULL; - void * pwArg = ss->pkcs11PinArg; + ssl3CipherSpec * pwSpec = ss->ssl3.pwSpec; + const ssl3KEADef *kea_def= ss->ssl3.hs.kea_def; + unsigned char * cr = (unsigned char *)&ss->ssl3.hs.client_random; + unsigned char * sr = (unsigned char *)&ss->ssl3.hs.server_random; PRBool isTLS = (PRBool)(kea_def->tls_keygen || (pwSpec->version > SSL_LIBRARY_VERSION_3_0)); - PRBool skipKeysAndIVs = (PRBool) - ((cipher_def->calg == calg_fortezza) || - (cipher_def->calg == calg_null)); /* * Whenever isDH is true, we need to use CKM_TLS_MASTER_KEY_DERIVE_DH * which, unlike CKM_TLS_MASTER_KEY_DERIVE, converts arbitrary size * data into a 48-byte value. */ - PRBool isDH = (PRBool) ((ss->ssl3->hs.kea_def->exchKeyType == kt_dh) || - (ss->ssl3->hs.kea_def->exchKeyType == kt_ecdh)); + PRBool isDH = (PRBool) ((ss->ssl3.hs.kea_def->exchKeyType == kt_dh) || + (ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh)); + SECStatus rv = SECFailure; CK_MECHANISM_TYPE master_derive; CK_MECHANISM_TYPE key_derive; - CK_MECHANISM_TYPE bulk_mechanism; SECItem params; - int keySize; CK_FLAGS keyFlags; CK_VERSION pms_version; - CK_SSL3_KEY_MAT_PARAMS key_material_params; - CK_SSL3_KEY_MAT_OUT returnedKeys; CK_SSL3_MASTER_KEY_DERIVE_PARAMS master_params; - SSLCipherAlgorithm calg; - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss)); - PORT_Assert( ssl_HaveSpecWriteLock(ss)); - PORT_Assert(ss->ssl3->prSpec == ss->ssl3->pwSpec); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); + PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); if (isTLS) { if(isDH) master_derive = CKM_TLS_MASTER_KEY_DERIVE_DH; else master_derive = CKM_TLS_MASTER_KEY_DERIVE; @@ -2361,7 +2422,7 @@ ssl3_GenerateSessionKeys(sslSocket *ss, const PK11SymKey *pms) pwSpec->master_secret = PK11_DeriveWithFlags((PK11SymKey *)pms, master_derive, ¶ms, key_derive, CKA_DERIVE, 0, keyFlags); - if (!isDH && pwSpec->master_secret && ss->detectRollBack) { + if (!isDH && pwSpec->master_secret && ss->opt.detectRollBack) { SSL3ProtocolVersion client_version; client_version = pms_version.major << 8 | pms_version.minor; if (client_version != ss->clientHelloVersion) { @@ -2405,9 +2466,81 @@ ssl3_GenerateSessionKeys(sslSocket *ss, const PK11SymKey *pms) } if (pwSpec->master_secret == NULL) { ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); - return SECFailure; + return rv; } + if (ss->opt.bypassPKCS11) { + SECItem * keydata; + /* In hope of doing a "double bypass", + * need to extract the master secret's value from the key object + * and store it raw in the sslSocket struct. + */ + rv = PK11_ExtractKeyValue(pwSpec->master_secret); + if (rv != SECSuccess) { + return rv; + } + /* This returns the address of the secItem inside the key struct, + * not a copy or a reference. So, there's no need to free it. + */ + keydata = PK11_GetKeyData(pwSpec->master_secret); + if (keydata && keydata->len <= sizeof pwSpec->raw_master_secret) { + memcpy(pwSpec->raw_master_secret, keydata->data, keydata->len); + pwSpec->msItem.data = pwSpec->raw_master_secret; + pwSpec->msItem.len = keydata->len; + } else { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + } + return SECSuccess; +} + +/* + * Derive encryption and MAC Keys (and IVs) from master secret + * Sets a useful error code when returning SECFailure. + * + * Called only from ssl3_InitPendingCipherSpec(), + * which in turn is called from + * sendRSAClientKeyExchange (for Full handshake) + * sendDHClientKeyExchange (for Full handshake) + * ssl3_HandleClientKeyExchange (for Full handshake) + * ssl3_HandleServerHello (for session restart) + * ssl3_HandleClientHello (for session restart) + * Caller MUST hold the specWriteLock, and SSL3HandshakeLock. + * ssl3_InitPendingCipherSpec does that. + * + */ +static SECStatus +ssl3_DeriveConnectionKeysPKCS11(sslSocket *ss) +{ + ssl3CipherSpec * pwSpec = ss->ssl3.pwSpec; + const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def; + unsigned char * cr = (unsigned char *)&ss->ssl3.hs.client_random; + unsigned char * sr = (unsigned char *)&ss->ssl3.hs.server_random; + PRBool isTLS = (PRBool)(kea_def->tls_keygen || + (pwSpec->version > SSL_LIBRARY_VERSION_3_0)); + /* following variables used in PKCS11 path */ + const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def; + PK11SlotInfo * slot = NULL; + PK11SymKey * symKey = NULL; + void * pwArg = ss->pkcs11PinArg; + int keySize; + CK_SSL3_KEY_MAT_PARAMS key_material_params; + CK_SSL3_KEY_MAT_OUT returnedKeys; + CK_MECHANISM_TYPE key_derive; + CK_MECHANISM_TYPE bulk_mechanism; + SSLCipherAlgorithm calg; + SECItem params; + PRBool skipKeysAndIVs = (PRBool)(cipher_def->calg == calg_null); + + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); + PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); + + if (!pwSpec->master_secret) { + PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); + return SECFailure; + } /* * generate the key material */ @@ -2443,6 +2576,12 @@ ssl3_GenerateSessionKeys(sslSocket *ss, const PK11SymKey *pms) params.data = (unsigned char *)&key_material_params; params.len = sizeof(key_material_params); + if (isTLS) { + key_derive = CKM_TLS_KEY_AND_MAC_DERIVE; + } else { + key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE; + } + /* CKM_SSL3_KEY_AND_MAC_DERIVE is defined to set ENCRYPT, DECRYPT, and * DERIVE by DEFAULT */ symKey = PK11_Derive(pwSpec->master_secret, key_derive, ¶ms, @@ -2506,19 +2645,23 @@ loser: static SECStatus ssl3_UpdateHandshakeHashes(sslSocket *ss, unsigned char *b, unsigned int l) { - ssl3State *ssl3 = ss->ssl3; - SECStatus rv; + SECStatus rv = SECSuccess; - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); PRINT_BUF(90, (NULL, "MD5 & SHA handshake hash input:", b, l)); - rv = PK11_DigestOp(ssl3->hs.md5, b, l); + if (ss->opt.bypassPKCS11) { + MD5_Update((MD5Context *)ss->ssl3.hs.md5_cx, b, l); + SHA1_Update((SHA1Context *)ss->ssl3.hs.sha_cx, b, l); + return rv; + } + rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l); if (rv != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); return rv; } - rv = PK11_DigestOp(ssl3->hs.sha, b, l); + rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l); if (rv != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); return rv; @@ -2531,14 +2674,14 @@ ssl3_UpdateHandshakeHashes(sslSocket *ss, unsigned char *b, unsigned int l) * All these functions set appropriate error codes. * Most rely on ssl3_AppendHandshake to set the error code. **************************************************************************/ -static SECStatus +SECStatus ssl3_AppendHandshake(sslSocket *ss, const void *void_src, PRInt32 bytes) { unsigned char * src = (unsigned char *)void_src; int room = ss->sec.ci.sendBuf.space - ss->sec.ci.sendBuf.len; SECStatus rv; - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); /* protects sendBuf. */ + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); /* protects sendBuf. */ if (ss->sec.ci.sendBuf.space < MAX_SEND_BUF_LENGTH && room < bytes) { rv = sslBuffer_Grow(&ss->sec.ci.sendBuf, PR_MAX(MIN_SEND_BUF_LENGTH, @@ -2594,7 +2737,7 @@ ssl3_AppendHandshakeNumber(sslSocket *ss, PRInt32 num, PRInt32 lenSize) return rv; /* error code set by AppendHandshake, if applicable. */ } -static SECStatus +SECStatus ssl3_AppendHandshakeVariable( sslSocket *ss, const SSL3Opaque *src, PRInt32 bytes, PRInt32 lenSize) { @@ -2614,7 +2757,7 @@ ssl3_AppendHandshakeVariable( return rv; /* error code set by AppendHandshake, if applicable. */ } -static SECStatus +SECStatus ssl3_AppendHandshakeHeader(sslSocket *ss, SSL3HandshakeType t, PRUint32 length) { SECStatus rv; @@ -2622,9 +2765,9 @@ ssl3_AppendHandshakeHeader(sslSocket *ss, SSL3HandshakeType t, PRUint32 length) SSL_TRC(30,("%d: SSL3[%d]: append handshake header: type %s", SSL_GETPID(), ss->fd, ssl3_DecodeHandshakeType(t))); PRINT_BUF(60, (ss, "MD5 handshake hash:", - (unsigned char*)ss->ssl3->hs.md5, MD5_LENGTH)); + (unsigned char*)ss->ssl3.hs.md5_cx, MD5_LENGTH)); PRINT_BUF(95, (ss, "SHA handshake hash:", - (unsigned char*)ss->ssl3->hs.sha, SHA1_LENGTH)); + (unsigned char*)ss->ssl3.hs.sha_cx, SHA1_LENGTH)); rv = ssl3_AppendHandshakeNumber(ss, t, 1); if (rv != SECSuccess) { @@ -2649,12 +2792,12 @@ ssl3_AppendHandshakeHeader(sslSocket *ss, SSL3HandshakeType t, PRUint32 length) * and has set a generic error code. The caller should probably * override the generic error code by setting another. */ -static SECStatus +SECStatus ssl3_ConsumeHandshake(sslSocket *ss, void *v, PRInt32 bytes, SSL3Opaque **b, PRUint32 *length) { - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); if ((PRUint32)bytes > *length) { return ssl3_DecodeError(ss); @@ -2681,18 +2824,23 @@ static PRInt32 ssl3_ConsumeHandshakeNumber(sslSocket *ss, PRInt32 bytes, SSL3Opaque **b, PRUint32 *length) { - PRInt32 num = 0; + uint8 *buf = *b; int i; - SECStatus status; - uint8 buf[4]; + PRInt32 num = 0; - status = ssl3_ConsumeHandshake(ss, buf, bytes, b, length); - if (status != SECSuccess) { - /* ssl3_DecodeError has already been called */ - return SECFailure; + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( bytes <= sizeof num); + + if ((PRUint32)bytes > *length) { + return ssl3_DecodeError(ss); } + PRINT_BUF(60, (ss, "consume bytes:", *b, bytes)); + for (i = 0; i < bytes; i++) num = (num << 8) + buf[i]; + *b += bytes; + *length -= bytes; return num; } @@ -2704,13 +2852,17 @@ ssl3_ConsumeHandshakeNumber(sslSocket *ss, PRInt32 bytes, SSL3Opaque **b, * * Returns SECFailure (-1) on failure. * On error, an alert has been sent, and a generic error code has been set. + * + * RADICAL CHANGE for NSS 3.11. All callers of this function make copies + * of the data returned in the SECItem *i, so making a copy of it here + * is simply wasteful. So, This function now just sets SECItem *i to + * point to the values in the buffer **b. */ -static SECStatus +SECStatus ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i, PRInt32 bytes, SSL3Opaque **b, PRUint32 *length) { PRInt32 count; - SECStatus rv; PORT_Assert(bytes <= 3); i->len = 0; @@ -2720,21 +2872,13 @@ ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i, PRInt32 bytes, return SECFailure; } if (count > 0) { - i->data = (unsigned char*)PORT_Alloc(count); - if (i->data == NULL) { - /* XXX inconsistent. In other places, we don't send alerts for - * our own memory failures. But here we do... */ - (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure); - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - i->len = count; - rv = ssl3_ConsumeHandshake(ss, i->data, i->len, b, length); - if (rv != SECSuccess) { - PORT_Free(i->data); - i->data = NULL; - return rv; /* alert has already been sent. */ + if ((PRUint32)count > *length) { + return ssl3_DecodeError(ss); } + i->data = *b; + i->len = count; + *b += count; + *length -= count; } return SECSuccess; } @@ -2758,155 +2902,241 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss, SSL3Hashes * hashes, /* output goes here. */ uint32 sender) { - ssl3State * ssl3 = ss->ssl3; - PK11Context * md5; - PK11Context * sha = NULL; SECStatus rv = SECSuccess; + PRBool isTLS = (PRBool)(spec->version > SSL_LIBRARY_VERSION_3_0); unsigned int outLength; - PRBool isTLS; SSL3Opaque md5_inner[MAX_MAC_LENGTH]; SSL3Opaque sha_inner[MAX_MAC_LENGTH]; - unsigned char s[4]; - unsigned char md5StackBuf[256]; - unsigned char shaStackBuf[512]; - unsigned char *md5StateBuf = NULL; - unsigned char *shaStateBuf = NULL; - unsigned int md5StateLen, shaStateLen; - - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); - - isTLS = (PRBool)(spec->version > SSL_LIBRARY_VERSION_3_0); - if (!spec->master_secret) { - PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); - return SECFailure; - } - - md5StateBuf = PK11_SaveContextAlloc(ssl3->hs.md5, md5StackBuf, - sizeof md5StackBuf, &md5StateLen); - if (md5StateBuf == NULL) { - ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); - goto loser; - } - md5 = ssl3->hs.md5; - shaStateBuf = PK11_SaveContextAlloc(ssl3->hs.sha, shaStackBuf, - sizeof shaStackBuf, &shaStateLen); - if (shaStateBuf == NULL) { - ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); - goto loser; - } - sha = ssl3->hs.sha; + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); - if (!isTLS) { - /* compute hashes for SSL3. */ + if (ss->opt.bypassPKCS11) { + /* compute them without PKCS11 */ + PRUint64 md5_cx[MAX_MAC_CONTEXT_LLONGS]; + PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS]; - s[0] = (unsigned char)(sender >> 24); - s[1] = (unsigned char)(sender >> 16); - s[2] = (unsigned char)(sender >> 8); - s[3] = (unsigned char)sender; +#define md5cx ((MD5Context *)md5_cx) +#define shacx ((SHA1Context *)sha_cx) - if (sender != 0) { - rv |= PK11_DigestOp(md5, s, 4); - PRINT_BUF(95, (NULL, "MD5 inner: sender", s, 4)); + if (!spec->msItem.data) { + PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); + return SECFailure; } - PRINT_BUF(95, (NULL, "MD5 inner: MAC Pad 1", mac_pad_1, mac_defs[mac_md5].pad_size)); + MD5_Clone (md5cx, (MD5Context *)ss->ssl3.hs.md5_cx); + SHA1_Clone(shacx, (SHA1Context *)ss->ssl3.hs.sha_cx); - rv |= PK11_DigestKey(md5,spec->master_secret); - rv |= PK11_DigestOp(md5, mac_pad_1, mac_defs[mac_md5].pad_size); - rv |= PK11_DigestFinal(md5, md5_inner, &outLength, MD5_LENGTH); - PORT_Assert(rv != SECSuccess || outLength == MD5_LENGTH); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); - rv = SECFailure; - goto loser; + if (!isTLS) { + /* compute hashes for SSL3. */ + unsigned char s[4]; + + s[0] = (unsigned char)(sender >> 24); + s[1] = (unsigned char)(sender >> 16); + s[2] = (unsigned char)(sender >> 8); + s[3] = (unsigned char)sender; + + if (sender != 0) { + MD5_Update(md5cx, s, 4); + PRINT_BUF(95, (NULL, "MD5 inner: sender", s, 4)); + } + + PRINT_BUF(95, (NULL, "MD5 inner: MAC Pad 1", mac_pad_1, + mac_defs[mac_md5].pad_size)); + + MD5_Update(md5cx, spec->msItem.data, spec->msItem.len); + MD5_Update(md5cx, mac_pad_1, mac_defs[mac_md5].pad_size); + MD5_End(md5cx, md5_inner, &outLength, MD5_LENGTH); + + PRINT_BUF(95, (NULL, "MD5 inner: result", md5_inner, outLength)); + + if (sender != 0) { + SHA1_Update(shacx, s, 4); + PRINT_BUF(95, (NULL, "SHA inner: sender", s, 4)); + } + + PRINT_BUF(95, (NULL, "SHA inner: MAC Pad 1", mac_pad_1, + mac_defs[mac_sha].pad_size)); + + SHA1_Update(shacx, spec->msItem.data, spec->msItem.len); + SHA1_Update(shacx, mac_pad_1, mac_defs[mac_sha].pad_size); + SHA1_End(shacx, sha_inner, &outLength, SHA1_LENGTH); + + PRINT_BUF(95, (NULL, "SHA inner: result", sha_inner, outLength)); + PRINT_BUF(95, (NULL, "MD5 outer: MAC Pad 2", mac_pad_2, + mac_defs[mac_md5].pad_size)); + PRINT_BUF(95, (NULL, "MD5 outer: MD5 inner", md5_inner, MD5_LENGTH)); + + MD5_Begin(md5cx); + MD5_Update(md5cx, spec->msItem.data, spec->msItem.len); + MD5_Update(md5cx, mac_pad_2, mac_defs[mac_md5].pad_size); + MD5_Update(md5cx, md5_inner, MD5_LENGTH); } + MD5_End(md5cx, hashes->md5, &outLength, MD5_LENGTH); - PRINT_BUF(95, (NULL, "MD5 inner: result", md5_inner, outLength)); + PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->md5, MD5_LENGTH)); - if (sender != 0) { - rv |= PK11_DigestOp(sha, s, 4); - PRINT_BUF(95, (NULL, "SHA inner: sender", s, 4)); + if (!isTLS) { + PRINT_BUF(95, (NULL, "SHA outer: MAC Pad 2", mac_pad_2, + mac_defs[mac_sha].pad_size)); + PRINT_BUF(95, (NULL, "SHA outer: SHA inner", sha_inner, SHA1_LENGTH)); + + SHA1_Begin(shacx); + SHA1_Update(shacx, spec->msItem.data, spec->msItem.len); + SHA1_Update(shacx, mac_pad_2, mac_defs[mac_sha].pad_size); + SHA1_Update(shacx, sha_inner, SHA1_LENGTH); } + SHA1_End(shacx, hashes->sha, &outLength, SHA1_LENGTH); - PRINT_BUF(95, (NULL, "SHA inner: MAC Pad 1", mac_pad_1, mac_defs[mac_sha].pad_size)); + PRINT_BUF(60, (NULL, "SHA outer: result", hashes->sha, SHA1_LENGTH)); + rv = SECSuccess; +#undef md5cx +#undef shacx + } else { + /* compute hases with PKCS11 */ + PK11Context * md5; + PK11Context * sha = NULL; + unsigned char *md5StateBuf = NULL; + unsigned char *shaStateBuf = NULL; + unsigned int md5StateLen, shaStateLen; + unsigned char md5StackBuf[256]; + unsigned char shaStackBuf[512]; + + if (!spec->master_secret) { + PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); + return SECFailure; + } - rv |= PK11_DigestKey(sha, spec->master_secret); - rv |= PK11_DigestOp(sha, mac_pad_1, mac_defs[mac_sha].pad_size); - rv |= PK11_DigestFinal(sha, sha_inner, &outLength, SHA1_LENGTH); - PORT_Assert(rv != SECSuccess || outLength == SHA1_LENGTH); - if (rv != SECSuccess) { + md5StateBuf = PK11_SaveContextAlloc(ss->ssl3.hs.md5, md5StackBuf, + sizeof md5StackBuf, &md5StateLen); + if (md5StateBuf == NULL) { + ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); + goto loser; + } + md5 = ss->ssl3.hs.md5; + + shaStateBuf = PK11_SaveContextAlloc(ss->ssl3.hs.sha, shaStackBuf, + sizeof shaStackBuf, &shaStateLen); + if (shaStateBuf == NULL) { ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); - rv = SECFailure; goto loser; } + sha = ss->ssl3.hs.sha; - PRINT_BUF(95, (NULL, "SHA inner: result", sha_inner, outLength)); + if (!isTLS) { + /* compute hashes for SSL3. */ + unsigned char s[4]; - PRINT_BUF(95, (NULL, "MD5 outer: MAC Pad 2", mac_pad_2, mac_defs[mac_md5].pad_size)); - PRINT_BUF(95, (NULL, "MD5 outer: MD5 inner", md5_inner, MD5_LENGTH)); + s[0] = (unsigned char)(sender >> 24); + s[1] = (unsigned char)(sender >> 16); + s[2] = (unsigned char)(sender >> 8); + s[3] = (unsigned char)sender; - rv |= PK11_DigestBegin(md5); - rv |= PK11_DigestKey(md5, spec->master_secret); - rv |= PK11_DigestOp(md5, mac_pad_2, mac_defs[mac_md5].pad_size); - rv |= PK11_DigestOp(md5, md5_inner, MD5_LENGTH); - } - rv |= PK11_DigestFinal(md5, hashes->md5, &outLength, MD5_LENGTH); - PORT_Assert(rv != SECSuccess || outLength == MD5_LENGTH); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); - rv = SECFailure; - goto loser; - } + if (sender != 0) { + rv |= PK11_DigestOp(md5, s, 4); + PRINT_BUF(95, (NULL, "MD5 inner: sender", s, 4)); + } - PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->md5, MD5_LENGTH)); + PRINT_BUF(95, (NULL, "MD5 inner: MAC Pad 1", mac_pad_1, + mac_defs[mac_md5].pad_size)); - if (!isTLS) { - PRINT_BUF(95, (NULL, "SHA outer: MAC Pad 2", mac_pad_2, mac_defs[mac_sha].pad_size)); - PRINT_BUF(95, (NULL, "SHA outer: SHA inner", sha_inner, SHA1_LENGTH)); + rv |= PK11_DigestKey(md5,spec->master_secret); + rv |= PK11_DigestOp(md5, mac_pad_1, mac_defs[mac_md5].pad_size); + rv |= PK11_DigestFinal(md5, md5_inner, &outLength, MD5_LENGTH); + PORT_Assert(rv != SECSuccess || outLength == MD5_LENGTH); + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); + rv = SECFailure; + goto loser; + } - rv |= PK11_DigestBegin(sha); - rv |= PK11_DigestKey(sha,spec->master_secret); - rv |= PK11_DigestOp(sha, mac_pad_2, mac_defs[mac_sha].pad_size); - rv |= PK11_DigestOp(sha, sha_inner, SHA1_LENGTH); - } - rv |= PK11_DigestFinal(sha, hashes->sha, &outLength, SHA1_LENGTH); - PORT_Assert(rv != SECSuccess || outLength == SHA1_LENGTH); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); - rv = SECFailure; - goto loser; - } + PRINT_BUF(95, (NULL, "MD5 inner: result", md5_inner, outLength)); - PRINT_BUF(60, (NULL, "SHA outer: result", hashes->sha, SHA1_LENGTH)); + if (sender != 0) { + rv |= PK11_DigestOp(sha, s, 4); + PRINT_BUF(95, (NULL, "SHA inner: sender", s, 4)); + } - rv = SECSuccess; + PRINT_BUF(95, (NULL, "SHA inner: MAC Pad 1", mac_pad_1, + mac_defs[mac_sha].pad_size)); -loser: - if (md5StateBuf) { - if (PK11_RestoreContext(ssl3->hs.md5, md5StateBuf, md5StateLen) - != SECSuccess) - { + rv |= PK11_DigestKey(sha, spec->master_secret); + rv |= PK11_DigestOp(sha, mac_pad_1, mac_defs[mac_sha].pad_size); + rv |= PK11_DigestFinal(sha, sha_inner, &outLength, SHA1_LENGTH); + PORT_Assert(rv != SECSuccess || outLength == SHA1_LENGTH); + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); + rv = SECFailure; + goto loser; + } + + PRINT_BUF(95, (NULL, "SHA inner: result", sha_inner, outLength)); + + PRINT_BUF(95, (NULL, "MD5 outer: MAC Pad 2", mac_pad_2, + mac_defs[mac_md5].pad_size)); + PRINT_BUF(95, (NULL, "MD5 outer: MD5 inner", md5_inner, MD5_LENGTH)); + + rv |= PK11_DigestBegin(md5); + rv |= PK11_DigestKey(md5, spec->master_secret); + rv |= PK11_DigestOp(md5, mac_pad_2, mac_defs[mac_md5].pad_size); + rv |= PK11_DigestOp(md5, md5_inner, MD5_LENGTH); + } + rv |= PK11_DigestFinal(md5, hashes->md5, &outLength, MD5_LENGTH); + PORT_Assert(rv != SECSuccess || outLength == MD5_LENGTH); + if (rv != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); rv = SECFailure; + goto loser; } - if (md5StateBuf != md5StackBuf) { - PORT_ZFree(md5StateBuf, md5StateLen); + + PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->md5, MD5_LENGTH)); + + if (!isTLS) { + PRINT_BUF(95, (NULL, "SHA outer: MAC Pad 2", mac_pad_2, + mac_defs[mac_sha].pad_size)); + PRINT_BUF(95, (NULL, "SHA outer: SHA inner", sha_inner, SHA1_LENGTH)); + + rv |= PK11_DigestBegin(sha); + rv |= PK11_DigestKey(sha,spec->master_secret); + rv |= PK11_DigestOp(sha, mac_pad_2, mac_defs[mac_sha].pad_size); + rv |= PK11_DigestOp(sha, sha_inner, SHA1_LENGTH); } - } - if (shaStateBuf) { - if (PK11_RestoreContext(ssl3->hs.sha, shaStateBuf, shaStateLen) - != SECSuccess) - { + rv |= PK11_DigestFinal(sha, hashes->sha, &outLength, SHA1_LENGTH); + PORT_Assert(rv != SECSuccess || outLength == SHA1_LENGTH); + if (rv != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); rv = SECFailure; + goto loser; + } + + PRINT_BUF(60, (NULL, "SHA outer: result", hashes->sha, SHA1_LENGTH)); + + rv = SECSuccess; + + loser: + if (md5StateBuf) { + if (PK11_RestoreContext(ss->ssl3.hs.md5, md5StateBuf, md5StateLen) + != SECSuccess) + { + ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); + rv = SECFailure; + } + if (md5StateBuf != md5StackBuf) { + PORT_ZFree(md5StateBuf, md5StateLen); + } } - if (shaStateBuf != shaStackBuf) { - PORT_ZFree(shaStateBuf, shaStateLen); + if (shaStateBuf) { + if (PK11_RestoreContext(ss->ssl3.hs.sha, shaStateBuf, shaStateLen) + != SECSuccess) + { + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); + rv = SECFailure; + } + if (shaStateBuf != shaStackBuf) { + PORT_ZFree(shaStateBuf, shaStateLen); + } } } - return rv; } @@ -2928,9 +3158,9 @@ ssl3_StartHandshakeHash(sslSocket *ss, unsigned char * buf, int length) goto done; /* ssl3_InitState has set the error code. */ } - PORT_Memset(&ss->ssl3->hs.client_random, 0, SSL3_RANDOM_LENGTH); + PORT_Memset(&ss->ssl3.hs.client_random, 0, SSL3_RANDOM_LENGTH); PORT_Memcpy( - &ss->ssl3->hs.client_random.rand[SSL3_RANDOM_LENGTH - SSL_CHALLENGE_BYTES], + &ss->ssl3.hs.client_random.rand[SSL3_RANDOM_LENGTH - SSL_CHALLENGE_BYTES], &ss->sec.ci.clientChallenge, SSL_CHALLENGE_BYTES); @@ -2966,8 +3196,8 @@ ssl3_SendClientHello(sslSocket *ss) SSL_TRC(3, ("%d: SSL3[%d]: send client_hello handshake", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); - PORT_Assert( ssl_HaveXmitBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); rv = ssl3_InitState(ss); if (rv != SECSuccess) { @@ -2976,59 +3206,60 @@ ssl3_SendClientHello(sslSocket *ss) SSL_TRC(30,("%d: SSL3[%d]: reset handshake hashes", SSL_GETPID(), ss->fd )); - rv = PK11_DigestBegin(ss->ssl3->hs.md5); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); - return rv; - } - rv = PK11_DigestBegin(ss->ssl3->hs.sha); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); - return rv; + if (ss->opt.bypassPKCS11) { + MD5_Begin((MD5Context *)ss->ssl3.hs.md5_cx); + SHA1_Begin((SHA1Context *)ss->ssl3.hs.sha_cx); + } else { + rv = PK11_DigestBegin(ss->ssl3.hs.md5); + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); + return rv; + } + rv = PK11_DigestBegin(ss->ssl3.hs.sha); + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); + return rv; + } } - /* We ignore ss->sec.ci.sid here, and use ssl_Lookup because Lookup * handles expired entries and other details. * XXX If we've been called from ssl2_BeginClientHandshake, then * this lookup is duplicative and wasteful. */ - sid = (ss->noCache) ? NULL + sid = (ss->opt.noCache) ? NULL : ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID, ss->url); /* We can't resume based on a different token. If the sid exists, * make sure the token that holds the master secret still exists ... * If we previously did client-auth, make sure that the token that holds * the private key still exists, is logged in, hasn't been removed, etc. - * Also for fortezza, make sure that the card that holds the session keys - * exist as well... */ + */ if (sid) { - PK11SlotInfo *slot; PRBool sidOK = PR_TRUE; - slot = (!sid->u.ssl3.masterValid) ? NULL : - SECMOD_LookupSlot(sid->u.ssl3.masterModuleID, - sid->u.ssl3.masterSlotID); - if (slot == NULL) { - sidOK = PR_FALSE; - } else { - PK11SymKey *wrapKey = NULL; - if (!PK11_IsPresent(slot) || - ((wrapKey = PK11_GetWrapKey(slot, sid->u.ssl3.masterWrapIndex, - sid->u.ssl3.masterWrapMech, - sid->u.ssl3.masterWrapSeries, - ss->pkcs11PinArg)) == NULL) ) { - sidOK = PR_FALSE; + if (sid->u.ssl3.keys.msIsWrapped) { + /* Session key was wrapped, which means it was using PKCS11, */ + PK11SlotInfo *slot = NULL; + if (sid->u.ssl3.masterValid && !ss->opt.bypassPKCS11) { + slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID, + sid->u.ssl3.masterSlotID); + } + if (slot == NULL) { + sidOK = PR_FALSE; + } else { + PK11SymKey *wrapKey = NULL; + if (!PK11_IsPresent(slot) || + ((wrapKey = PK11_GetWrapKey(slot, + sid->u.ssl3.masterWrapIndex, + sid->u.ssl3.masterWrapMech, + sid->u.ssl3.masterWrapSeries, + ss->pkcs11PinArg)) == NULL) ) { + sidOK = PR_FALSE; + } + if (wrapKey) PK11_FreeSymKey(wrapKey); + PK11_FreeSlot(slot); + slot = NULL; } - if (wrapKey) PK11_FreeSymKey(wrapKey); - PK11_FreeSlot(slot); - slot = NULL; - } - /* do sid-has-FORTEZZA-slot check */ - if (sid->u.ssl3.hasFortezza) { - /* do has fortezza check */ - if (!PK11_VerifyKeyOK(sid->u.ssl3.tek)) - sidOK = PR_FALSE; } - /* If we previously did client-auth, make sure that the token that ** holds the private key still exists, is logged in, hasn't been ** removed, etc. @@ -3055,7 +3286,7 @@ ssl3_SendClientHello(sslSocket *ss) PRINT_BUF(4, (ss, "client, found session-id:", sid->u.ssl3.sessionID, sid->u.ssl3.sessionIDLength)); - ss->ssl3->policy = sid->u.ssl3.policy; + ss->ssl3.policy = sid->u.ssl3.policy; } else { ++ssl3stats.sch_sid_cache_misses; @@ -3070,7 +3301,7 @@ ssl3_SendClientHello(sslSocket *ss) } ssl_GetSpecWriteLock(ss); - cwSpec = ss->ssl3->cwSpec; + cwSpec = ss->ssl3.cwSpec; if (cwSpec->mac_def->mac == mac_null) { /* SSL records are not being MACed. */ cwSpec->version = ss->version; @@ -3085,8 +3316,8 @@ ssl3_SendClientHello(sslSocket *ss) ss->sec.send = ssl3_SendApplicationData; /* shouldn't get here if SSL3 is disabled, but ... */ - PORT_Assert(ss->enableSSL3 || ss->enableTLS); - if (!ss->enableSSL3 && !ss->enableTLS) { + PORT_Assert(ss->opt.enableSSL3 || ss->opt.enableTLS); + if (!ss->opt.enableSSL3 && !ss->opt.enableTLS) { PORT_SetError(SSL_ERROR_SSL_DISABLED); return SECFailure; } @@ -3097,7 +3328,7 @@ ssl3_SendClientHello(sslSocket *ss) return SECFailure; /* ssl3_config_match_init has set error code. */ /* how many suites are permitted by policy and user preference? */ - num_suites = count_cipher_suites(ss, ss->ssl3->policy, PR_TRUE); + num_suites = count_cipher_suites(ss, ss->ssl3.policy, PR_TRUE); if (!num_suites) return SECFailure; /* count_cipher_suites has set error code. */ @@ -3116,11 +3347,11 @@ ssl3_SendClientHello(sslSocket *ss) if (rv != SECSuccess) { return rv; /* err set by ssl3_AppendHandshake* */ } - rv = ssl3_GetNewRandom(&ss->ssl3->hs.client_random); + rv = ssl3_GetNewRandom(&ss->ssl3.hs.client_random); if (rv != SECSuccess) { return rv; /* err set by GetNewRandom. */ } - rv = ssl3_AppendHandshake(ss, &ss->ssl3->hs.client_random, + rv = ssl3_AppendHandshake(ss, &ss->ssl3.hs.client_random, SSL3_RANDOM_LENGTH); if (rv != SECSuccess) { return rv; /* err set by ssl3_AppendHandshake* */ @@ -3143,7 +3374,7 @@ ssl3_SendClientHello(sslSocket *ss) for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) { ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i]; - if (config_match(suite, ss->ssl3->policy, PR_TRUE)) { + if (config_match(suite, ss->ssl3.policy, PR_TRUE)) { actual_count++; if (actual_count > num_suites) { /* set error card removal/insertion error */ @@ -3183,7 +3414,7 @@ ssl3_SendClientHello(sslSocket *ss) return rv; /* error code set by ssl3_FlushHandshake */ } - ss->ssl3->hs.ws = wait_server_hello; + ss->ssl3.hs.ws = wait_server_hello; return rv; } @@ -3201,13 +3432,12 @@ ssl3_HandleHelloRequest(sslSocket *ss) SSL_TRC(3, ("%d: SSL3[%d]: handle hello_request handshake", SSL_GETPID(), ss->fd)); - PORT_Assert(ss->ssl3); - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); - if (ss->ssl3->hs.ws == wait_server_hello) + if (ss->ssl3.hs.ws == wait_server_hello) return SECSuccess; - if (ss->ssl3->hs.ws != idle_handshake || ss->sec.isServer) { + if (ss->ssl3.hs.ws != idle_handshake || ss->sec.isServer) { (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST); return SECFailure; @@ -3279,35 +3509,6 @@ ssl_UnwrapSymWrappingKey( PORT_Assert(wrappedKey.len <= sizeof pWswk->wrappedSymmetricWrappingkey); switch (exchKeyType) { - PK11SymKey * Ks; - PK11SlotInfo * slot; - SECItem param; - - case kt_fortezza: - /* get the slot that the fortezza server private key is in. */ - slot = PK11_GetSlotFromPrivateKey(svrPrivKey); - if (slot == NULL) { - SET_ERROR_CODE - goto loser; - } - - /* Look up the Token Fixed Key */ - Ks = PK11_FindFixedKey(slot, CKM_SKIPJACK_CBC64, NULL, pwArg); - PK11_FreeSlot(slot); - if (Ks == NULL) { - SET_ERROR_CODE - goto loser; - } - - /* unwrap client write key with the local Ks and IV */ - param.type = siBuffer; - param.data = pWswk->wrapIV; - param.len = pWswk->wrapIVLen; - unwrappedWrappingKey = - PK11_UnwrapSymKey(Ks, CKM_SKIPJACK_CBC64, ¶m, &wrappedKey, - masterWrapMech, CKA_UNWRAP, 0); - PK11_FreeSymKey(Ks); - break; case kt_rsa: unwrappedWrappingKey = @@ -3391,7 +3592,7 @@ getWrappingKey( sslSocket * ss, SECItem wrappedKey; SSLWrappedSymWrappingKey wswk; - svrPrivKey = ss->serverCerts[exchKeyType].serverKey; + svrPrivKey = ss->serverCerts[exchKeyType].SERVERKEY; PORT_Assert(svrPrivKey != NULL); if (!svrPrivKey) { return NULL; /* why are we here?!? */ @@ -3466,36 +3667,6 @@ getWrappingKey( sslSocket * ss, /* wrap symmetric wrapping key in server's public key. */ switch (exchKeyType) { - PK11SymKey * Ks; - PK11SlotInfo * fSlot; - SECItem param; - - case kt_fortezza: - /* get the slot that the fortezza server private key is in. */ - fSlot = PK11_GetSlotFromPrivateKey(svrPrivKey); - if (fSlot == NULL) { - SET_ERROR_CODE - goto loser; - } - - /* Look up the Token Fixed Key */ - Ks = PK11_FindFixedKey(fSlot, CKM_SKIPJACK_CBC64, NULL, pwArg); - PK11_FreeSlot(fSlot); - if (Ks == NULL) { - SET_ERROR_CODE - goto loser; - } - - /* wrap symmetricWrapping key with the local Ks */ - param.type = siBuffer; - param.data = wswk.wrapIV; - param.len = sizeof wswk.wrapIV; - rv = PK11_WrapSymKey(CKM_SKIPJACK_CBC64, ¶m, Ks, - unwrappedWrappingKey, &wrappedKey); - wswk.wrapIVLen = param.len; - PK11_FreeSymKey(Ks); - asymWrapMechanism = CKM_SKIPJACK_CBC64; - break; case kt_rsa: asymWrapMechanism = CKM_RSA_PKCS; @@ -3554,21 +3725,8 @@ done: } -static SECStatus -ssl3_FortezzaAppendHandshake(sslSocket *ss, unsigned char * data, int len) -{ - SSL3FortezzaKeys *fortezza_CKE = NULL; - SECStatus rv = SECFailure; - - rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, - (sizeof(*fortezza_CKE)-sizeof(fortezza_CKE->y_c)) + 1 + len); - if (rv == SECSuccess) { - rv = ssl3_AppendHandshakeVariable(ss, data, len, 1); - } - return rv; /* err set by ssl3_AppendHandshake* */ -} - /* Called from ssl3_SendClientKeyExchange(). */ +/* Presently, this always uses PKCS11. There is no bypass for this. */ static SECStatus sendRSAClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) { @@ -3577,14 +3735,14 @@ sendRSAClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) SECItem enc_pms = {siBuffer, NULL, 0}; PRBool isTLS; - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); - PORT_Assert( ssl_HaveXmitBufLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); /* Generate the pre-master secret ... */ ssl_GetSpecWriteLock(ss); - isTLS = (PRBool)(ss->ssl3->pwSpec->version > SSL_LIBRARY_VERSION_3_0); + isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); - pms = ssl3_GenerateRSAPMS(ss, ss->ssl3->pwSpec, NULL); + pms = ssl3_GenerateRSAPMS(ss, ss->ssl3.pwSpec, NULL); ssl_ReleaseSpecWriteLock(ss); if (pms == NULL) { ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); @@ -3640,6 +3798,7 @@ loser: } /* Called from ssl3_SendClientKeyExchange(). */ +/* Presently, this always uses PKCS11. There is no bypass for this. */ static SECStatus sendDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) { @@ -3652,10 +3811,10 @@ sendDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) SECKEYPublicKey *pubKey = NULL; /* Ephemeral DH key */ SECKEYPrivateKey *privKey = NULL; /* Ephemeral DH key */ - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); - PORT_Assert( ssl_HaveXmitBufLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); - isTLS = (PRBool)(ss->ssl3->pwSpec->version > SSL_LIBRARY_VERSION_3_0); + isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); /* Copy DH parameters from server key */ @@ -3725,522 +3884,9 @@ loser: return rv; } -#ifdef NSS_ENABLE_ECC -/* Called from ssl3_SendClientKeyExchange(). */ -static SECStatus -sendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) -{ - PK11SymKey * pms = NULL; - SECStatus rv = SECFailure; - PRBool isTLS; - CK_MECHANISM_TYPE target; - SECKEYPublicKey *pubKey = NULL; /* Ephemeral ECDH key */ - SECKEYPrivateKey *privKey = NULL; /* Ephemeral ECDH key */ - CK_EC_KDF_TYPE kdf; - - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); - PORT_Assert( ssl_HaveXmitBufLock(ss)); - - isTLS = (PRBool)(ss->ssl3->pwSpec->version > SSL_LIBRARY_VERSION_3_0); - - /* Generate ephemeral EC keypair */ - privKey = SECKEY_CreateECPrivateKey(&svrPubKey->u.ec.DEREncodedParams, - &pubKey, NULL); - if (!privKey || !pubKey) { - ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL); - rv = SECFailure; - goto loser; - } - PRINT_BUF(50, (ss, "ECDH public value:", - pubKey->u.ec.publicValue.data, - pubKey->u.ec.publicValue.len)); - - if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH; - else target = CKM_SSL3_MASTER_KEY_DERIVE_DH; - - /* If field size is not more than 24 octets, then use SHA-1 hash of result; - * otherwise, use result (see section 4.8 of draft-ietf-tls-ecc-03.txt). - */ - if ((pubKey->u.ec.publicValue.len - 1) / 2 <= 24) { - kdf = CKD_SHA1_KDF; - } else { - kdf = CKD_NULL; - } - - /* Determine the PMS */ - pms = PK11_PubDeriveWithKDF(privKey, svrPubKey, PR_FALSE, NULL, NULL, - CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0, - kdf, NULL, NULL); - - if (pms == NULL) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto loser; - } - - SECKEY_DestroyPrivateKey(privKey); - privKey = NULL; - - rv = ssl3_InitPendingCipherSpec(ss, pms); - PK11_FreeSymKey(pms); pms = NULL; - - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto loser; - } - - rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, - pubKey->u.ec.publicValue.len + 1); - if (rv != SECSuccess) { - goto loser; /* err set by ssl3_AppendHandshake* */ - } - - rv = ssl3_AppendHandshakeVariable(ss, - pubKey->u.ec.publicValue.data, - pubKey->u.ec.publicValue.len, 1); - SECKEY_DestroyPublicKey(pubKey); - pubKey = NULL; - - if (rv != SECSuccess) { - goto loser; /* err set by ssl3_AppendHandshake* */ - } - - rv = SECSuccess; - -loser: - if(pms) PK11_FreeSymKey(pms); - if(privKey) SECKEY_DestroyPrivateKey(privKey); - if(pubKey) SECKEY_DestroyPublicKey(pubKey); - return rv; -} -#endif /* NSS_ENABLE_ECC */ - -/* fortezza client-auth portion of ClientKeyExchange message - * This function appends the KEA public key from the client's V3 cert - * (empty for a V1 cert) to the outgoing ClientKeyExchange message. - * For a V3 cert, it also computes the Fortezza public key hash of that key - * and signs that hash with the client's signing private key. - * It also finds and returns the client's KEA private key. - * - * Called from sendFortezzaClientKeyExchange <- ssl3_SendClientKeyExchange() - */ -static SECKEYPrivateKey * -sendFortezzaCKXClientAuth(sslSocket *ss, SSL3FortezzaKeys * fortezza_CKE) -{ - SECKEYPublicKey * pubKey = NULL; - SECKEYPrivateKey * privKeaKey = NULL; - CERTCertificate * peerCert = ss->sec.peerCert; - void * pwArg = ss->pkcs11PinArg; - SECStatus rv = SECFailure; - SECItem sigItem; - SECItem hashItem; - - /* extract our own local public key. */ - pubKey = CERT_ExtractPublicKey(ss->ssl3->clientCertificate); - if (!pubKey) { - ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE); - goto loser; - } - - if (pubKey->keyType == fortezzaKey) { - /* fortezza clientauth with fortezza V1 certificate */ - rv = ssl3_FortezzaAppendHandshake(ss, NULL, 0); - if (rv != SECSuccess) { - goto loser; /* err was set by AppendHandshake. */ - } - privKeaKey = PK11_FindKeyByAnyCert(ss->ssl3->clientCertificate, pwArg); - if (!privKeaKey) { - ssl_MapLowLevelError(SEC_ERROR_NO_KEY); - } - - } else { - /* fortezza clientauth w/ V3 certificate or non fortezza cert*/ - CERTCertificate * ccert = NULL; - SECKEYPublicKey * foundPubKey = NULL; - unsigned char hash[SHA1_LENGTH]; - ccert = PK11_FindBestKEAMatch(peerCert, pwArg); - if (ccert == NULL) { - PORT_SetError(SSL_ERROR_FORTEZZA_PQG); - goto v3_loser; - } - foundPubKey = CERT_ExtractPublicKey(ccert); - if (foundPubKey == NULL) { - ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE); - goto v3_loser; - } - if (foundPubKey->keyType == keaKey) { - rv = ssl3_FortezzaAppendHandshake(ss, - foundPubKey->u.kea.publicValue.data, - foundPubKey->u.kea.publicValue.len); - if (rv != SECSuccess) { - goto v3_loser; /* err was set by AppendHandshake. */ - } - - rv = ssl3_ComputeFortezzaPublicKeyHash( - foundPubKey->u.kea.publicValue, hash); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto v3_loser; - } - } else { - rv = ssl3_FortezzaAppendHandshake(ss, - foundPubKey->u.fortezza.KEAKey.data, - foundPubKey->u.fortezza.KEAKey.len); - if (rv != SECSuccess) { - goto v3_loser; /* err was set by AppendHandshake. */ - } - - rv = ssl3_ComputeFortezzaPublicKeyHash( - foundPubKey->u.fortezza.KEAKey, hash); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto v3_loser; - } - } - - hashItem.data = (unsigned char *) hash; - hashItem.len = SHA1_LENGTH; - - sigItem.data = fortezza_CKE->y_signature; - sigItem.len = sizeof fortezza_CKE->y_signature; - - rv = PK11_Sign(ss->ssl3->clientPrivateKey, &sigItem, &hashItem); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto v3_loser; - } - - privKeaKey = PK11_FindKeyByAnyCert(ccert, pwArg); - if (!privKeaKey) { - ssl_MapLowLevelError(SEC_ERROR_NO_KEY); - } - -v3_loser: - if (foundPubKey) - SECKEY_DestroyPublicKey(foundPubKey); - if (ccert) - CERT_DestroyCertificate(ccert); - } /* fortezza clientauth w/ V3 certificate or non fortezza cert*/ - -loser: - - if (pubKey) - SECKEY_DestroyPublicKey(pubKey); - return privKeaKey; -} /* End of fortezza client-auth. */ - - -/* fortezza without client-auth */ -/* fortezza client-auth portion of ClientKeyExchange message - * This function appends the public KEA key from the client's cert - * to the outgoing ClientKeyExchange message. - * It also finds and returns the client's KEA private key. - * - * Called from sendFortezzaClientKeyExchange <- ssl3_SendClientKeyExchange() - */ -static SECKEYPrivateKey * -sendFortezzaCKXNoClientAuth(sslSocket *ss) -{ - SECKEYPublicKey * foundPubKey = NULL; - SECKEYPrivateKey * privKeaKey = NULL; - CERTCertificate * ccert = NULL; - CERTCertificate * peerCert = ss->sec.peerCert; - void * pwArg = ss->pkcs11PinArg; - SECStatus rv = SECFailure; - - ccert = PK11_FindBestKEAMatch(peerCert, pwArg); - if (ccert == NULL) { - PORT_SetError(SSL_ERROR_FORTEZZA_PQG); - goto loser; - } - - foundPubKey = CERT_ExtractPublicKey(ccert); - if (foundPubKey == NULL) { - ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE); - goto loser; - } - - if (foundPubKey->keyType == fortezzaKey) { - /* fortezza V1 cert */ - rv = ssl3_FortezzaAppendHandshake(ss, - foundPubKey->u.fortezza.KEAKey.data, - foundPubKey->u.fortezza.KEAKey.len); - if (rv != SECSuccess) { - goto loser; /* err was set by AppendHandshake. */ - } - privKeaKey = PK11_FindKeyByAnyCert(ccert, pwArg); - if (!privKeaKey) { - ssl_MapLowLevelError(SEC_ERROR_NO_KEY); - } - } else { - /* fortezza V3 cert */ - rv = ssl3_FortezzaAppendHandshake(ss, - foundPubKey->u.kea.publicValue.data, - foundPubKey->u.kea.publicValue.len); - if (rv != SECSuccess) { - goto loser; /* err was set by AppendHandshake. */ - } - privKeaKey = PK11_FindKeyByAnyCert(ccert, pwArg); - if (!privKeaKey) { - ssl_MapLowLevelError(SEC_ERROR_NO_KEY); - } - } - -loser: - if (foundPubKey) - SECKEY_DestroyPublicKey(foundPubKey); - if (ccert) - CERT_DestroyCertificate(ccert); - return privKeaKey; -} - -/* Called from ssl3_SendClientKeyExchange(). */ -static SECStatus -sendFortezzaClientKeyExchange(sslSocket * ss, SECKEYPublicKey * serverKey) -{ - ssl3CipherSpec * pwSpec = NULL; - sslSessionID * sid = ss->sec.ci.sid; - PK11SlotInfo * slot = NULL; - PK11SymKey * pms = NULL; - PK11SymKey * tek = NULL; - PK11SymKey * client_write_key = NULL; - PK11SymKey * server_write_key = NULL; - SECKEYPrivateKey * privKeaKey = NULL; - void * pwArg = ss->pkcs11PinArg; - SECStatus rv = SECFailure; - CK_VERSION version; - SECItem param; - SECItem raItem; - SECItem rbItem; - SECItem enc_pms; - SECItem item; - SSL3FortezzaKeys fortezza_CKE; - PRBool releaseSpecWriteLock = PR_FALSE; - - PORT_Assert( ssl_HaveXmitBufLock(ss)); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); - - /* first get an appropriate slot for doing MACing. - * Note: This slot will NOT be a Fortezza slot because Fortezza - * cannot generate an SSL3 pre-master-secret. - */ - slot = PK11_GetBestSlot(CKM_SSL3_PRE_MASTER_KEY_GEN, pwArg); - if (slot == NULL) { - PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND); - goto loser; - } - - /* create a pre-Master secret */ - version.major = MSB(ss->version); - version.minor = LSB(ss->version); - - param.data = (unsigned char *)&version; - param.len = sizeof version; - - pms = PK11_KeyGen(slot, CKM_SSL3_PRE_MASTER_KEY_GEN, - ¶m, 0, pwArg); - PK11_FreeSlot(slot); - slot = NULL; - if (pms == NULL) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto loser; - } - - /* If we don't have a certificate, we need to read out your public key. - * This changes a bit when we need to deal with the PQG stuff - */ - PORT_Memset(fortezza_CKE.y_signature, 0, sizeof fortezza_CKE.y_signature); - - /* Send the KEA public key and get the KEA private key. */ - if (ss->ssl3->clientCertificate != NULL) { - /* with client-auth */ - privKeaKey = sendFortezzaCKXClientAuth(ss, &fortezza_CKE); - } else { - /* without client-auth */ - privKeaKey = sendFortezzaCKXNoClientAuth(ss); - } - if (privKeaKey == NULL) { - rv = SECFailure; - goto loser; /* error was already set. */ - } - - /* Now we derive the TEK, and generate r_c the client's "random" public key. - * r_c is generated and filled in by the PubDerive call below. - */ - raItem.data = fortezza_CKE.r_c; - raItem.len = sizeof fortezza_CKE.r_c; - - /* R_s == server's "random" public key, sent in the Server Key Exchange */ - rbItem.data = ss->ssl3->fortezza.R_s; - rbItem.len = sizeof ss->ssl3->fortezza.R_s; - - tek = PK11_PubDerive(privKeaKey, serverKey, PR_TRUE, /* generate r_c */ - &raItem, &rbItem, CKM_KEA_KEY_DERIVE, - CKM_SKIPJACK_WRAP, CKA_WRAP, 0, pwArg); - SECKEY_DestroyPrivateKey(privKeaKey); - privKeaKey = NULL; - if (tek == NULL) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto loser; - } - - ss->ssl3->fortezza.tek = PK11_ReferenceSymKey(tek); /* can't fail. */ - - /* encrypt the pms with the TEK. - * NB: PK11_WrapSymKey will generate and output the encrypted PMS - * AND the IV for decrypting the PMS. - */ - param.data = fortezza_CKE.master_secret_iv; - param.len = sizeof fortezza_CKE.master_secret_iv; - - enc_pms.data = fortezza_CKE.encrypted_preMasterSecret; - enc_pms.len = sizeof fortezza_CKE.encrypted_preMasterSecret; - - rv = PK11_WrapSymKey(CKM_SKIPJACK_CBC64, ¶m, tek, pms, &enc_pms); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto loser; - } - rv = SECFailure; /* not there yet. */ - - slot = PK11_GetSlotFromKey(tek); - - ssl_GetSpecWriteLock(ss); releaseSpecWriteLock = PR_TRUE; - - pwSpec = ss->ssl3->pwSpec; - pwSpec->client.write_key = client_write_key = - PK11_KeyGen(slot, CKM_SKIPJACK_CBC64, NULL, 0, pwArg); - if (client_write_key == NULL) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto loser; - } - /* the -1 is a hack. It's supposed to be key size, but we use it - * to tell the wrapper that we're doing a weird PKCS #11 key gen. - * Usually the result of key gen is an encrypt key. This is not - * the case with SSL, where this key is a decrypt key. - */ - pwSpec->server.write_key = server_write_key = - PK11_KeyGen(slot, CKM_SKIPJACK_CBC64, NULL, -1, pwArg); - if (server_write_key == NULL) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto loser; - } - - rv = ssl3_InitPendingCipherSpec(ss, pms); - PK11_FreeSymKey(pms); pms = NULL; - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto loser; - } - - /* copy the keys and IVs out now */ - item.data = fortezza_CKE.wrapped_client_write_key; - item.len = sizeof fortezza_CKE.wrapped_client_write_key; - rv = PK11_WrapSymKey(CKM_SKIPJACK_WRAP, NULL, tek, client_write_key, &item); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto loser; - } - - item.data = fortezza_CKE.wrapped_server_write_key; - item.len = sizeof fortezza_CKE.wrapped_server_write_key; - rv = PK11_WrapSymKey(CKM_SKIPJACK_WRAP, NULL, tek, server_write_key, &item); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto loser; - } - - /* we only get the generated IV's if we're doing skipjack. */ - if (pwSpec->cipher_def->calg == calg_fortezza) { - PORT_Memcpy(fortezza_CKE.client_write_iv, pwSpec->client.write_iv, - sizeof fortezza_CKE.client_write_iv); - PORT_Memcpy(fortezza_CKE.server_write_iv, pwSpec->server.write_iv, - sizeof fortezza_CKE.server_write_iv); - } else { - /* generate IVs to make old servers happy */ - rv = PK11_GenerateFortezzaIV(client_write_key, - fortezza_CKE.client_write_iv, - sizeof fortezza_CKE.client_write_iv); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto loser; - } - rv = PK11_GenerateFortezzaIV(server_write_key, - fortezza_CKE.server_write_iv, - sizeof fortezza_CKE.server_write_iv); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto loser; - } - } - - /* NOTE: This technique of writing out the struct, rather than writing - * out the individual members works only because all the rest of the - * values are fixed-length strings of well-defined byte order. - * Add one SECItem or one Number and we will need to break the elements out. - */ - rv = ssl3_AppendHandshake(ss, &fortezza_CKE.r_c, - (sizeof fortezza_CKE - sizeof fortezza_CKE.y_c)); - if (rv != SECSuccess) { - goto loser; /* err was set by AppendHandshake. */ - } - - /* now we initialize our contexts */ - sid->u.ssl3.hasFortezza = PR_TRUE; - sid->u.ssl3.tek = tek; tek = NULL; /* adopt.. */ - - if (pwSpec->cipher_def->calg == calg_fortezza) { - sid->u.ssl3.clientWriteKey = - PK11_ReferenceSymKey(pwSpec->client.write_key); - sid->u.ssl3.serverWriteKey= - PK11_ReferenceSymKey(pwSpec->server.write_key); - - PORT_Memcpy(sid->u.ssl3.keys.client_write_iv, - pwSpec->client.write_iv, - sizeof sid->u.ssl3.keys.client_write_iv); - PORT_Memcpy(sid->u.ssl3.keys.server_write_iv, - pwSpec->server.write_iv, - sizeof sid->u.ssl3.keys.server_write_iv); - - rv = PK11_SaveContext((PK11Context *)pwSpec->encodeContext, - sid->u.ssl3.clientWriteSave, - &sid->u.ssl3.clientWriteSaveLen, - sizeof sid->u.ssl3.clientWriteSave); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto loser; - } - } else { - PK11_FreeSymKey(client_write_key); - pwSpec->client.write_key = client_write_key = NULL; - - PK11_FreeSymKey(server_write_key); - pwSpec->server.write_key = server_write_key = NULL; - - rv = SECSuccess; - } - /* FALL THROUGH */ - -loser: - if (tek) PK11_FreeSymKey(tek); - if (slot) PK11_FreeSlot(slot); - if (pms) PK11_FreeSymKey(pms); - if (rv != SECSuccess) { - if (client_write_key) { - PK11_FreeSymKey(client_write_key); - pwSpec->client.write_key = client_write_key = NULL; - } - if (server_write_key) { - PK11_FreeSymKey(server_write_key); - pwSpec->server.write_key = server_write_key = NULL; - } - } - if (releaseSpecWriteLock) - ssl_GetSpecWriteLock(ss); - return rv; -} /* Called from ssl3_HandleServerHelloDone(). */ static SECStatus @@ -4253,8 +3899,8 @@ ssl3_SendClientKeyExchange(sslSocket *ss) SSL_TRC(3, ("%d: SSL3[%d]: send client_key_exchange handshake", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveXmitBufLock(ss)); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); if (ss->sec.peerKey == NULL) { serverKey = CERT_ExtractPublicKey(ss->sec.peerCert); @@ -4267,12 +3913,12 @@ ssl3_SendClientKeyExchange(sslSocket *ss) ss->sec.peerKey = NULL; /* we're done with it now */ } - isTLS = (PRBool)(ss->ssl3->pwSpec->version > SSL_LIBRARY_VERSION_3_0); + isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); /* enforce limits on kea key sizes. */ - if (ss->ssl3->hs.kea_def->is_limited) { + if (ss->ssl3.hs.kea_def->is_limited) { int keyLen = SECKEY_PublicKeyStrength(serverKey); /* bytes */ - if (keyLen * BPB > ss->ssl3->hs.kea_def->key_size_limit) { + if (keyLen * BPB > ss->ssl3.hs.kea_def->key_size_limit) { if (isTLS) (void)SSL3_SendAlert(ss, alert_fatal, export_restriction); else @@ -4282,25 +3928,21 @@ ssl3_SendClientKeyExchange(sslSocket *ss) } } - ss->sec.keaType = ss->ssl3->hs.kea_def->exchKeyType; + ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType; ss->sec.keaKeyBits = SECKEY_PublicKeyStrengthInBits(serverKey); - switch (ss->ssl3->hs.kea_def->exchKeyType) { + switch (ss->ssl3.hs.kea_def->exchKeyType) { case kt_rsa: rv = sendRSAClientKeyExchange(ss, serverKey); break; - case kt_fortezza: - rv = sendFortezzaClientKeyExchange(ss, serverKey); - break; - case kt_dh: rv = sendDHClientKeyExchange(ss, serverKey); break; #ifdef NSS_ENABLE_ECC case kt_ecdh: - rv = sendECDHClientKeyExchange(ss, serverKey); + rv = ssl3_SendECDHClientKeyExchange(ss, serverKey); break; #endif /* NSS_ENABLE_ECC */ @@ -4324,27 +3966,26 @@ loser: static SECStatus ssl3_SendCertificateVerify(sslSocket *ss) { - ssl3State * ssl3 = ss->ssl3; SECStatus rv = SECFailure; PRBool isTLS; SECItem buf = {siBuffer, NULL, 0}; SSL3Hashes hashes; - PORT_Assert( ssl_HaveXmitBufLock(ss)); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); SSL_TRC(3, ("%d: SSL3[%d]: send certificate_verify handshake", SSL_GETPID(), ss->fd)); ssl_GetSpecReadLock(ss); - rv = ssl3_ComputeHandshakeHashes(ss, ssl3->pwSpec, &hashes, 0); + rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, 0); ssl_ReleaseSpecReadLock(ss); if (rv != SECSuccess) { goto done; /* err code was set by ssl3_ComputeHandshakeHashes */ } - isTLS = (PRBool)(ssl3->pwSpec->version > SSL_LIBRARY_VERSION_3_0); - rv = ssl3_SignHashes(&hashes, ssl3->clientPrivateKey, &buf, isTLS); + isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); + rv = ssl3_SignHashes(&hashes, ss->ssl3.clientPrivateKey, &buf, isTLS); if (rv == SECSuccess) { PK11SlotInfo * slot; sslSessionID * sid = ss->sec.ci.sid; @@ -4353,7 +3994,7 @@ ssl3_SendCertificateVerify(sslSocket *ss) ** Later, when doing an SSL restart handshake, verify this. ** These calls are mere accessors, and can't fail. */ - slot = PK11_GetSlotFromPrivateKey(ss->ssl3->clientPrivateKey); + slot = PK11_GetSlotFromPrivateKey(ss->ssl3.clientPrivateKey); sid->u.ssl3.clAuthSeries = PK11_GetSlotSeries(slot); sid->u.ssl3.clAuthSlotID = PK11_GetSlotID(slot); sid->u.ssl3.clAuthModuleID = PK11_GetModuleID(slot); @@ -4361,12 +4002,12 @@ ssl3_SendCertificateVerify(sslSocket *ss) PK11_FreeSlot(slot); } /* If we're doing RSA key exchange, we're all done with the private key - * here. Diffie-Hellman & Fortezza key exchanges need the client's + * here. Diffie-Hellman key exchanges need the client's * private key for the key exchange. */ - if (ssl3->hs.kea_def->exchKeyType == kt_rsa) { - SECKEY_DestroyPrivateKey(ssl3->clientPrivateKey); - ssl3->clientPrivateKey = NULL; + if (ss->ssl3.hs.kea_def->exchKeyType == kt_rsa) { + SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); + ss->ssl3.clientPrivateKey = NULL; } if (rv != SECSuccess) { goto done; /* err code was set by ssl3_SignHashes */ @@ -4408,15 +4049,15 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) SSL_TRC(3, ("%d: SSL3[%d]: handle server_hello handshake", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); rv = ssl3_InitState(ss); if (rv != SECSuccess) { errCode = PORT_GetError(); /* ssl3_InitState has set the error code. */ goto alert_loser; } - if (ss->ssl3->hs.ws != wait_server_hello) { + if (ss->ssl3.hs.ws != wait_server_hello) { errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO; desc = unexpected_message; goto alert_loser; @@ -4432,20 +4073,22 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) ** know SSL 3.x. */ if (MSB(version) != MSB(SSL_LIBRARY_VERSION_3_0)) { - desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version : handshake_failure; + desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version + : handshake_failure; goto alert_loser; } rv = ssl3_NegotiateVersion(ss, version); if (rv != SECSuccess) { - desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version : handshake_failure; + desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version + : handshake_failure; errCode = SSL_ERROR_NO_CYPHER_OVERLAP; goto alert_loser; } isTLS = (ss->version > SSL_LIBRARY_VERSION_3_0); rv = ssl3_ConsumeHandshake( - ss, &ss->ssl3->hs.server_random, SSL3_RANDOM_LENGTH, &b, &length); + ss, &ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH, &b, &length); if (rv != SECSuccess) { goto loser; /* alert has been sent */ } @@ -4469,7 +4112,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) { ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i]; if ((temp == suite->cipher_suite) && - (config_match(suite, ss->ssl3->policy, PR_TRUE))) { + (config_match(suite, ss->ssl3.policy, PR_TRUE))) { suite_found = PR_TRUE; break; /* success */ } @@ -4479,10 +4122,10 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) errCode = SSL_ERROR_NO_CYPHER_OVERLAP; goto alert_loser; } - ss->ssl3->hs.cipher_suite = (ssl3CipherSuite)temp; - ss->ssl3->hs.suite_def = ssl_LookupCipherSuiteDef((ssl3CipherSuite)temp); - PORT_Assert(ss->ssl3->hs.suite_def); - if (!ss->ssl3->hs.suite_def) { + ss->ssl3.hs.cipher_suite = (ssl3CipherSuite)temp; + ss->ssl3.hs.suite_def = ssl_LookupCipherSuiteDef((ssl3CipherSuite)temp); + PORT_Assert(ss->ssl3.hs.suite_def); + if (!ss->ssl3.hs.suite_def) { PORT_SetError(errCode = SEC_ERROR_LIBRARY_FAILURE); goto loser; /* we don't send alerts for our screw-ups. */ } @@ -4504,18 +4147,20 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) errCode = SSL_ERROR_NO_COMPRESSION_OVERLAP; goto alert_loser; } - ss->ssl3->hs.compression = (SSL3CompressionMethod)temp; + ss->ssl3.hs.compression = (SSL3CompressionMethod)temp; +#ifdef DISALLOW_SERVER_HELLO_EXTENSIONS if (length != 0) { /* malformed */ goto alert_loser; } +#endif /* Any errors after this point are not "malformed" errors. */ desc = handshake_failure; /* we need to call ssl3_SetupPendingCipherSpec here so we can check the * key exchange algorithm. */ - rv = ssl3_SetupPendingCipherSpec(ss, ss->ssl3); + rv = ssl3_SetupPendingCipherSpec(ss); if (rv != SECSuccess) { goto alert_loser; /* error code is set. */ } @@ -4531,96 +4176,105 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) if (sid_match && sid->version == ss->version && - sid->u.ssl3.cipherSuite == ss->ssl3->hs.cipher_suite) do { - PK11SlotInfo *slot; - PK11SymKey * wrapKey; /* wrapping key */ + sid->u.ssl3.cipherSuite == ss->ssl3.hs.cipher_suite) do { + ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec; + SECItem wrappedMS; /* wrapped master secret. */ - CK_FLAGS keyFlags = 0; - ss->sec.authAlgorithm = sid->authAlgorithm; + ss->sec.authAlgorithm = sid->authAlgorithm; ss->sec.authKeyBits = sid->authKeyBits; ss->sec.keaType = sid->keaType; ss->sec.keaKeyBits = sid->keaKeyBits; - slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID, - sid->u.ssl3.masterSlotID); - if (slot == NULL) { - break; /* not considered an error. */ - } - if (!PK11_IsPresent(slot)) { + /* 3 cases here: + * a) key is wrapped (implies using PKCS11) + * b) key is unwrapped, but we're still using PKCS11 + * c) key is unwrapped, and we're bypassing PKCS11. + */ + if (sid->u.ssl3.keys.msIsWrapped) { + PK11SlotInfo *slot; + PK11SymKey * wrapKey; /* wrapping key */ + CK_FLAGS keyFlags = 0; + + if (ss->opt.bypassPKCS11) { + /* we cannot restart a non-bypass session in a + ** bypass socket. + */ + break; + } + /* unwrap master secret with PKCS11 */ + slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID, + sid->u.ssl3.masterSlotID); + if (slot == NULL) { + break; /* not considered an error. */ + } + if (!PK11_IsPresent(slot)) { + PK11_FreeSlot(slot); + break; /* not considered an error. */ + } + wrapKey = PK11_GetWrapKey(slot, sid->u.ssl3.masterWrapIndex, + sid->u.ssl3.masterWrapMech, + sid->u.ssl3.masterWrapSeries, + ss->pkcs11PinArg); PK11_FreeSlot(slot); - break; /* not considered an error. */ - } - wrapKey = PK11_GetWrapKey(slot, sid->u.ssl3.masterWrapIndex, - sid->u.ssl3.masterWrapMech, - sid->u.ssl3.masterWrapSeries, - ss->pkcs11PinArg); - PK11_FreeSlot(slot); - if (wrapKey == NULL) { - break; /* not considered an error. */ - } + if (wrapKey == NULL) { + break; /* not considered an error. */ + } - if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */ - keyFlags = CKF_SIGN | CKF_VERIFY; - } + if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */ + keyFlags = CKF_SIGN | CKF_VERIFY; + } - wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; - wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; - ss->ssl3->pwSpec->master_secret = - PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech, - NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE, - CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags); - errCode = PORT_GetError(); - PK11_FreeSymKey(wrapKey); - if (ss->ssl3->pwSpec->master_secret == NULL) { - break; /* errorCode set just after call to UnwrapSymKey. */ + wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; + wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; + pwSpec->master_secret = + PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech, + NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE, + CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags); + errCode = PORT_GetError(); + PK11_FreeSymKey(wrapKey); + if (pwSpec->master_secret == NULL) { + break; /* errorCode set just after call to UnwrapSymKey. */ + } + } else if (ss->opt.bypassPKCS11) { + /* MS is not wrapped */ + wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; + wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; + memcpy(pwSpec->raw_master_secret, wrappedMS.data, wrappedMS.len); + pwSpec->msItem.data = pwSpec->raw_master_secret; + pwSpec->msItem.len = wrappedMS.len; + } else { + /* We CAN restart a bypass session in a non-bypass socket. */ + /* need to import the raw master secret to session object */ + PK11SlotInfo *slot = PK11_GetInternalSlot(); + wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; + wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; + pwSpec->master_secret = + PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, + PK11_OriginUnwrap, CKA_ENCRYPT, + &wrappedMS, NULL); + PK11_FreeSlot(slot); + if (pwSpec->master_secret == NULL) { + break; + } } /* Got a Match */ ++ssl3stats.hsh_sid_cache_hits; - ss->ssl3->hs.ws = wait_change_cipher; - ss->ssl3->hs.isResuming = PR_TRUE; + ss->ssl3.hs.ws = wait_change_cipher; + ss->ssl3.hs.isResuming = PR_TRUE; /* copy the peer cert from the SID */ if (sid->peerCert != NULL) { ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); } - /* reload the FORTEZZA key material. These keys aren't generated - * by the master secret, but by the key exchange. We restart by - * reusing these keys. */ - if (sid->u.ssl3.hasFortezza) { - ss->ssl3->fortezza.tek = PK11_ReferenceSymKey(sid->u.ssl3.tek); - } - if (ss->ssl3->hs.suite_def->bulk_cipher_alg == cipher_fortezza) { - ss->ssl3->pwSpec->client.write_key = - PK11_ReferenceSymKey(sid->u.ssl3.clientWriteKey); - ss->ssl3->pwSpec->server.write_key = - PK11_ReferenceSymKey(sid->u.ssl3.serverWriteKey); - /* add the tek later for pre-encrypted files */ - PORT_Memcpy(ss->ssl3->pwSpec->client.write_iv, - sid->u.ssl3.keys.client_write_iv, - sizeof sid->u.ssl3.keys.client_write_iv); - PORT_Memcpy(ss->ssl3->pwSpec->server.write_iv, - sid->u.ssl3.keys.server_write_iv, - sizeof sid->u.ssl3.keys.server_write_iv); - } /* NULL value for PMS signifies re-use of the old MS */ rv = ssl3_InitPendingCipherSpec(ss, NULL); if (rv != SECSuccess) { - goto alert_loser; /* err code was set by ssl3_InitPendingCipherSpec */ - } - if (ss->ssl3->hs.suite_def->bulk_cipher_alg == cipher_fortezza) { - rv = PK11_RestoreContext( - (PK11Context *)ss->ssl3->pwSpec->encodeContext, - sid->u.ssl3.clientWriteSave, - sid->u.ssl3.clientWriteSaveLen); - if (rv != SECSuccess) { - goto alert_loser; /* err is set. */ - } + goto alert_loser; /* err code was set */ } - SECITEM_ZfreeItem(&sidBytes, PR_FALSE); return SECSuccess; } while (0); @@ -4630,7 +4284,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) ++ssl3stats.hsh_sid_cache_misses; /* throw the old one away */ - sid->u.ssl3.resumable = PR_FALSE; + sid->u.ssl3.keys.resumable = PR_FALSE; (*ss->sec.uncache)(sid); ssl_FreeSID(sid); @@ -4643,18 +4297,15 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) sid->version = ss->version; sid->u.ssl3.sessionIDLength = sidBytes.len; PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len); - SECITEM_ZfreeItem(&sidBytes, PR_FALSE); - ss->ssl3->hs.isResuming = PR_FALSE; - ss->ssl3->hs.ws = wait_server_cert; + ss->ssl3.hs.isResuming = PR_FALSE; + ss->ssl3.hs.ws = wait_server_cert; return SECSuccess; alert_loser: (void)SSL3_SendAlert(ss, alert_fatal, desc); loser: - if (sidBytes.data != NULL) - SECITEM_ZfreeItem(&sidBytes, PR_FALSE); errCode = ssl_MapLowLevelError(errCode); return SECFailure; } @@ -4672,25 +4323,16 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) SECStatus rv; int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH; SSL3AlertDescription desc = illegal_parameter; - SECItem modulus = {siBuffer, NULL, 0}; - SECItem exponent = {siBuffer, NULL, 0}; - SECItem signature = {siBuffer, NULL, 0}; - SECItem dh_p = {siBuffer, NULL, 0}; - SECItem dh_g = {siBuffer, NULL, 0}; - SECItem dh_Ys = {siBuffer, NULL, 0}; SSL3Hashes hashes; -#ifdef NSS_ENABLE_ECC - SECItem ec_params = {siBuffer, NULL, 0}; - SECItem ec_point = {siBuffer, NULL, 0}; -#endif /* NSS_ENABLE_ECC */ + SECItem signature = {siBuffer, NULL, 0}; SSL_TRC(3, ("%d: SSL3[%d]: handle server_key_exchange handshake", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); - if (ss->ssl3->hs.ws != wait_server_key && - ss->ssl3->hs.ws != wait_server_cert) { + if (ss->ssl3.hs.ws != wait_server_key && + ss->ssl3.hs.ws != wait_server_cert) { errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH; desc = unexpected_message; goto alert_loser; @@ -4701,11 +4343,14 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) goto alert_loser; } - isTLS = (PRBool)(ss->ssl3->prSpec->version > SSL_LIBRARY_VERSION_3_0); + isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0); - switch (ss->ssl3->hs.kea_def->exchKeyType) { + switch (ss->ssl3.hs.kea_def->exchKeyType) { + + case kt_rsa: { + SECItem modulus = {siBuffer, NULL, 0}; + SECItem exponent = {siBuffer, NULL, 0}; - case kt_rsa: rv = ssl3_ConsumeHandshakeVariable(ss, &modulus, 2, &b, &length); if (rv != SECSuccess) { goto loser; /* malformed. */ @@ -4732,8 +4377,9 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) * check to make sure the hash is signed by right guy */ rv = ssl3_ComputeExportRSAKeyHash(modulus, exponent, - &ss->ssl3->hs.client_random, - &ss->ssl3->hs.server_random, &hashes); + &ss->ssl3.hs.client_random, + &ss->ssl3.hs.server_random, + &hashes, ss->opt.bypassPKCS11); if (rv != SECSuccess) { errCode = ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); @@ -4774,13 +4420,15 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) goto no_memory; } ss->sec.peerKey = peerKey; - SECITEM_FreeItem(&modulus, PR_FALSE); - SECITEM_FreeItem(&exponent, PR_FALSE); - SECITEM_FreeItem(&signature, PR_FALSE); - ss->ssl3->hs.ws = wait_cert_request; + ss->ssl3.hs.ws = wait_cert_request; return SECSuccess; + } + + case kt_dh: { + SECItem dh_p = {siBuffer, NULL, 0}; + SECItem dh_g = {siBuffer, NULL, 0}; + SECItem dh_Ys = {siBuffer, NULL, 0}; - case kt_dh: rv = ssl3_ConsumeHandshakeVariable(ss, &dh_p, 2, &b, &length); if (rv != SECSuccess) { goto loser; /* malformed. */ @@ -4815,8 +4463,9 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) * check to make sure the hash is signed by right guy */ rv = ssl3_ComputeDHKeyHash(dh_p, dh_g, dh_Ys, - &ss->ssl3->hs.client_random, - &ss->ssl3->hs.server_random, &hashes); + &ss->ssl3.hs.client_random, + &ss->ssl3.hs.server_random, + &hashes, ss->opt.bypassPKCS11); if (rv != SECSuccess) { errCode = ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); @@ -4858,142 +4507,16 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) goto no_memory; } ss->sec.peerKey = peerKey; - SECITEM_FreeItem(&dh_p, PR_FALSE); - SECITEM_FreeItem(&dh_g, PR_FALSE); - SECITEM_FreeItem(&dh_Ys, PR_FALSE); - ss->ssl3->hs.ws = wait_cert_request; + ss->ssl3.hs.ws = wait_cert_request; return SECSuccess; + } #ifdef NSS_ENABLE_ECC case kt_ecdh: - /* XXX This works only for named curves, revisit this when - * we support generic curves. - */ - ec_params.len = 2; - ec_params.data = (unsigned char*)PORT_Alloc(ec_params.len); - rv = ssl3_ConsumeHandshake(ss, ec_params.data, ec_params.len, &b, &length); - if (rv != SECSuccess) { - goto loser; /* malformed. */ - } - - /* Fail if the curve is not a named curve */ - if ((ec_params.data[0] != ec_type_named) || - !supportedCurve(ec_params.data[1])) { - errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE; - desc = handshake_failure; - goto alert_loser; - } - - rv = ssl3_ConsumeHandshakeVariable(ss, &ec_point, 1, &b, &length); - if (rv != SECSuccess) { - goto loser; /* malformed. */ - } - /* Fail if the ec point uses compressed representation */ - if (ec_point.data[0] != EC_POINT_FORM_UNCOMPRESSED) { - errCode = SEC_ERROR_UNSUPPORTED_EC_POINT_FORM; - desc = handshake_failure; - goto alert_loser; - } - - rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length); - if (rv != SECSuccess) { - goto loser; /* malformed. */ - } - - if (length != 0) { - if (isTLS) - desc = decode_error; - goto alert_loser; /* malformed. */ - } - - PRINT_BUF(60, (NULL, "Server EC params", ec_params.data, - ec_params.len)); - PRINT_BUF(60, (NULL, "Server EC point", ec_point.data, ec_point.len)); - - /* failures after this point are not malformed handshakes. */ - /* TLS: send decrypt_error if signature failed. */ - desc = isTLS ? decrypt_error : handshake_failure; - - /* - * check to make sure the hash is signed by right guy - */ - rv = ssl3_ComputeECDHKeyHash(ec_params, ec_point, - &ss->ssl3->hs.client_random, - &ss->ssl3->hs.server_random, &hashes); - - if (rv != SECSuccess) { - errCode = - ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); - goto alert_loser; - } - rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature, - isTLS, ss->pkcs11PinArg); - if (rv != SECSuccess) { - errCode = - ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); - goto alert_loser; - } - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (arena == NULL) { - goto no_memory; - } - - ss->sec.peerKey = peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey); - if (peerKey == NULL) { - goto no_memory; - } - - peerKey->arena = arena; - peerKey->keyType = ecKey; - - /* set up EC parameters in peerKey */ - if (ecName2params(arena, ec_params.data[1], - &peerKey->u.ec.DEREncodedParams) != SECSuccess) { - /* we should never get here since we already - * checked that we are dealing with a supported curve - */ - errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE; - goto alert_loser; - } - - /* copy publicValue in peerKey */ - if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue, &ec_point)) - { - PORT_FreeArena(arena, PR_FALSE); - goto no_memory; - } - peerKey->pkcs11Slot = NULL; - peerKey->pkcs11ID = CK_INVALID_HANDLE; - - ss->sec.peerKey = peerKey; - SECITEM_FreeItem(&ec_params, PR_FALSE); - SECITEM_FreeItem(&ec_point, PR_FALSE); - ss->ssl3->hs.ws = wait_cert_request; - - return SECSuccess; + rv = ssl3_HandleECDHServerKeyExchange(ss, b, length); + return rv; #endif /* NSS_ENABLE_ECC */ - case kt_fortezza: - - /* Fortezza needs *BOTH* a server cert message - * and a server key exchange message. - */ - if (ss->ssl3->hs.ws == wait_server_cert) { - errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH; - desc = unexpected_message; - goto alert_loser; - } - /* Get the server's "random" public key. */ - rv = ssl3_ConsumeHandshake(ss, ss->ssl3->fortezza.R_s, - sizeof ss->ssl3->fortezza.R_s, &b, &length); - if (rv != SECSuccess) { - goto loser; /* malformed */ - } - - ss->ssl3->hs.ws = wait_cert_request; - return SECSuccess; - default: desc = handshake_failure; errCode = SEC_ERROR_UNSUPPORTED_KEYALG; @@ -5003,30 +4526,10 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) alert_loser: (void)SSL3_SendAlert(ss, alert_fatal, desc); loser: - if (modulus.data != NULL) SECITEM_FreeItem(&modulus, PR_FALSE); - if (exponent.data != NULL) SECITEM_FreeItem(&exponent, PR_FALSE); - if (signature.data != NULL) SECITEM_FreeItem(&signature, PR_FALSE); - if (dh_p.data != NULL) SECITEM_FreeItem(&dh_p, PR_FALSE); - if (dh_g.data != NULL) SECITEM_FreeItem(&dh_g, PR_FALSE); - if (dh_Ys.data != NULL) SECITEM_FreeItem(&dh_Ys, PR_FALSE); -#ifdef NSS_ENABLE_ECC - if (ec_params.data != NULL) SECITEM_FreeItem(&ec_params, PR_FALSE); - if (ec_point.data != NULL) SECITEM_FreeItem(&ec_point, PR_FALSE); -#endif /* NSS_ENABLE_ECC */ PORT_SetError( errCode ); return SECFailure; no_memory: /* no-memory error has already been set. */ - if (modulus.data != NULL) SECITEM_FreeItem(&modulus, PR_FALSE); - if (exponent.data != NULL) SECITEM_FreeItem(&exponent, PR_FALSE); - if (signature.data != NULL) SECITEM_FreeItem(&signature, PR_FALSE); - if (dh_p.data != NULL) SECITEM_FreeItem(&dh_p, PR_FALSE); - if (dh_g.data != NULL) SECITEM_FreeItem(&dh_g, PR_FALSE); - if (dh_Ys.data != NULL) SECITEM_FreeItem(&dh_Ys, PR_FALSE); -#ifdef NSS_ENABLE_ECC - if (ec_params.data != NULL) SECITEM_FreeItem(&ec_params, PR_FALSE); - if (ec_point.data != NULL) SECITEM_FreeItem(&ec_point, PR_FALSE); -#endif /* NSS_ENABLE_ECC */ ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); return SECFailure; } @@ -5044,7 +4547,6 @@ typedef struct dnameNode { static SECStatus ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) { - ssl3State * ssl3 = ss->ssl3; PRArenaPool * arena = NULL; dnameNode * node; PRInt32 remaining; @@ -5059,23 +4561,23 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_request handshake", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); - if (ssl3->hs.ws != wait_cert_request && - ssl3->hs.ws != wait_server_key) { + if (ss->ssl3.hs.ws != wait_cert_request && + ss->ssl3.hs.ws != wait_server_key) { desc = unexpected_message; errCode = SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST; goto alert_loser; } /* clean up anything left from previous handshake. */ - if (ssl3->clientCertChain != NULL) { - CERT_DestroyCertificateList(ssl3->clientCertChain); - ssl3->clientCertChain = NULL; + if (ss->ssl3.clientCertChain != NULL) { + CERT_DestroyCertificateList(ss->ssl3.clientCertChain); + ss->ssl3.clientCertChain = NULL; } - isTLS = (PRBool)(ssl3->prSpec->version > SSL_LIBRARY_VERSION_3_0); + isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0); rv = ssl3_ConsumeHandshakeVariable(ss, &cert_types, 1, &b, &length); if (rv != SECSuccess) goto loser; /* malformed, alert has been sent */ @@ -5124,7 +4626,7 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } ca_list.nnames = nnames; - ca_list.names = (SECItem*)PORT_ArenaAlloc(arena, nnames * sizeof(SECItem)); + ca_list.names = PORT_ArenaNewArray(arena, SECItem, nnames); if (nnames > 0 && ca_list.names == NULL) goto no_mem; @@ -5138,7 +4640,7 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) goto alert_loser; /* malformed */ desc = no_certificate; - ssl3->hs.ws = wait_hello_done; + ss->ssl3.hs.ws = wait_hello_done; if (ss->getClientAuthData == NULL) { rv = SECFailure; /* force it to send a no_certificate alert */ @@ -5146,8 +4648,8 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) /* XXX Should pass cert_types in this call!! */ rv = (SECStatus)(*ss->getClientAuthData)(ss->getClientAuthDataArg, ss->fd, &ca_list, - &ssl3->clientCertificate, - &ssl3->clientPrivateKey); + &ss->ssl3.clientCertificate, + &ss->ssl3.clientPrivateKey); } switch (rv) { case SECWouldBlock: /* getClientAuthData has put up a dialog box. */ @@ -5156,33 +4658,34 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) case SECSuccess: /* check what the callback function returned */ - if ((!ssl3->clientCertificate) || (!ssl3->clientPrivateKey)) { + if ((!ss->ssl3.clientCertificate) || (!ss->ssl3.clientPrivateKey)) { /* we are missing either the key or cert */ - if (ssl3->clientCertificate) { + if (ss->ssl3.clientCertificate) { /* got a cert, but no key - free it */ - CERT_DestroyCertificate(ssl3->clientCertificate); - ssl3->clientCertificate = NULL; + CERT_DestroyCertificate(ss->ssl3.clientCertificate); + ss->ssl3.clientCertificate = NULL; } - if (ssl3->clientPrivateKey) { + if (ss->ssl3.clientPrivateKey) { /* got a key, but no cert - free it */ - SECKEY_DestroyPrivateKey(ssl3->clientPrivateKey); - ssl3->clientPrivateKey = NULL; + SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); + ss->ssl3.clientPrivateKey = NULL; } goto send_no_certificate; } - /* Setting ssl3->clientCertChain non-NULL will cause + /* Setting ssl3.clientCertChain non-NULL will cause * ssl3_HandleServerHelloDone to call SendCertificate. */ - ssl3->clientCertChain = CERT_CertChainFromCert(ssl3->clientCertificate, - certUsageSSLClient, PR_FALSE); - if (ssl3->clientCertChain == NULL) { - if (ssl3->clientCertificate != NULL) { - CERT_DestroyCertificate(ssl3->clientCertificate); - ssl3->clientCertificate = NULL; + ss->ssl3.clientCertChain = CERT_CertChainFromCert( + ss->ssl3.clientCertificate, + certUsageSSLClient, PR_FALSE); + if (ss->ssl3.clientCertChain == NULL) { + if (ss->ssl3.clientCertificate != NULL) { + CERT_DestroyCertificate(ss->ssl3.clientCertificate); + ss->ssl3.clientCertificate = NULL; } - if (ssl3->clientPrivateKey != NULL) { - SECKEY_DestroyPrivateKey(ssl3->clientPrivateKey); - ssl3->clientPrivateKey = NULL; + if (ss->ssl3.clientPrivateKey != NULL) { + SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); + ss->ssl3.clientPrivateKey = NULL; } goto send_no_certificate; } @@ -5192,7 +4695,7 @@ ssl3_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length) default: send_no_certificate: if (isTLS) { - ssl3->sendEmptyCert = PR_TRUE; + ss->ssl3.sendEmptyCert = PR_TRUE; } else { (void)SSL3_SendAlert(ss, alert_warning, no_certificate); } @@ -5216,8 +4719,6 @@ loser: done: if (arena != NULL) PORT_FreeArena(arena, PR_FALSE); - if (cert_types.data != NULL) - SECITEM_FreeItem(&cert_types, PR_FALSE); return rv; } @@ -5261,16 +4762,16 @@ ssl3_RestartHandshakeAfterCertReq(sslSocket * ss, */ if (ss->handshake != 0) { ss->handshake = ssl_GatherRecord1stHandshake; - ss->ssl3->clientCertificate = cert; - ss->ssl3->clientCertChain = certChain; + ss->ssl3.clientCertificate = cert; + ss->ssl3.clientCertChain = certChain; if (key == NULL) { (void)SSL3_SendAlert(ss, alert_warning, no_certificate); - ss->ssl3->clientPrivateKey = NULL; + ss->ssl3.clientPrivateKey = NULL; } else { - ss->ssl3->clientPrivateKey = SECKEY_CopyPrivateKey(key); + ss->ssl3.clientPrivateKey = SECKEY_CopyPrivateKey(key); } ssl_GetRecvBufLock(ss); - if (ss->ssl3->hs.msgState.buf != NULL) { + if (ss->ssl3.hs.msgState.buf != NULL) { rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf); } ssl_ReleaseRecvBufLock(ss); @@ -5289,13 +4790,13 @@ static SECStatus ssl3_HandleServerHelloDone(sslSocket *ss) { SECStatus rv; - SSL3WaitState ws = ss->ssl3->hs.ws; + SSL3WaitState ws = ss->ssl3.hs.ws; PRBool send_verify = PR_FALSE; SSL_TRC(3, ("%d: SSL3[%d]: handle server_hello_done handshake", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); if (ws != wait_hello_done && ws != wait_server_cert && @@ -5308,16 +4809,16 @@ ssl3_HandleServerHelloDone(sslSocket *ss) ssl_GetXmitBufLock(ss); /*******************************/ - if (ss->ssl3->sendEmptyCert) { - ss->ssl3->sendEmptyCert = PR_FALSE; + if (ss->ssl3.sendEmptyCert) { + ss->ssl3.sendEmptyCert = PR_FALSE; rv = ssl3_SendEmptyCertificate(ss); /* Don't send verify */ if (rv != SECSuccess) { goto loser; /* error code is set. */ } } else - if (ss->ssl3->clientCertChain != NULL && - ss->ssl3->clientPrivateKey != NULL) { + if (ss->ssl3.clientCertChain != NULL && + ss->ssl3.clientPrivateKey != NULL) { send_verify = PR_TRUE; rv = ssl3_SendCertificate(ss); if (rv != SECSuccess) { @@ -5347,7 +4848,7 @@ ssl3_HandleServerHelloDone(sslSocket *ss) ssl_ReleaseXmitBufLock(ss); /*******************************/ - ss->ssl3->hs.ws = wait_change_cipher; + ss->ssl3.hs.ws = wait_change_cipher; return SECSuccess; loser: @@ -5366,8 +4867,8 @@ ssl3_SendHelloRequest(sslSocket *ss) SSL_TRC(3, ("%d: SSL3[%d]: send hello_request handshake", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); - PORT_Assert( ssl_HaveXmitBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); rv = ssl3_AppendHandshakeHeader(ss, hello_request, 0); if (rv != SECSuccess) { @@ -5377,7 +4878,7 @@ ssl3_SendHelloRequest(sslSocket *ss) if (rv != SECSuccess) { return rv; /* error code set by ssl3_FlushHandshake */ } - ss->ssl3->hs.ws = wait_client_hello; + ss->ssl3.hs.ws = wait_client_hello; return SECSuccess; } @@ -5405,12 +4906,10 @@ ssl3_NewSessionID(sslSocket *ss, PRBool is_server) sid->cached = never_cached; sid->version = ss->version; - sid->u.ssl3.resumable = PR_TRUE; + sid->u.ssl3.keys.resumable = PR_TRUE; sid->u.ssl3.policy = SSL_ALLOWED; - sid->u.ssl3.hasFortezza = PR_FALSE; sid->u.ssl3.clientWriteKey = NULL; sid->u.ssl3.serverWriteKey = NULL; - sid->u.ssl3.tek = NULL; if (is_server) { SECStatus rv; @@ -5440,8 +4939,8 @@ ssl3_SendServerHelloSequence(sslSocket *ss) SSL_TRC(3, ("%d: SSL3[%d]: begin send server_hello sequence", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); - PORT_Assert( ssl_HaveXmitBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); rv = ssl3_SendServerHello(ss); if (rv != SECSuccess) { @@ -5454,26 +4953,22 @@ ssl3_SendServerHelloSequence(sslSocket *ss) /* We have to do this after the call to ssl3_SendServerHello, * because kea_def is set up by ssl3_SendServerHello(). */ - kea_def = ss->ssl3->hs.kea_def; - ss->ssl3->hs.usedStepDownKey = PR_FALSE; - if (kea_def->kea == kea_fortezza) { - rv = ssl3_SendServerKeyExchange(ss); - if (rv != SECSuccess) { - return rv; /* err code was set. */ - } - } else if (kea_def->is_limited && kea_def->exchKeyType == kt_rsa) { + kea_def = ss->ssl3.hs.kea_def; + ss->ssl3.hs.usedStepDownKey = PR_FALSE; + + if (kea_def->is_limited && kea_def->exchKeyType == kt_rsa) { /* see if we can legally use the key in the cert. */ int keyLen; /* bytes */ keyLen = PK11_GetPrivateModulusLen( - ss->serverCerts[kea_def->exchKeyType].serverKey); + ss->serverCerts[kea_def->exchKeyType].SERVERKEY); if (keyLen > 0 && keyLen * BPB <= kea_def->key_size_limit ) { /* XXX AND cert is not signing only!! */ /* just fall through and use it. */ } else if (ss->stepDownKeyPair != NULL) { - ss->ssl3->hs.usedStepDownKey = PR_TRUE; + ss->ssl3.hs.usedStepDownKey = PR_TRUE; rv = ssl3_SendServerKeyExchange(ss); if (rv != SECSuccess) { return rv; /* err code was set. */ @@ -5494,7 +4989,7 @@ ssl3_SendServerHelloSequence(sslSocket *ss) #endif /* NSS_ENABLE_ECC */ } - if (ss->requestCertificate) { + if (ss->opt.requestCertificate) { rv = ssl3_SendCertificateRequest(ss); if (rv != SECSuccess) { return rv; /* err code is set. */ @@ -5505,7 +5000,7 @@ ssl3_SendServerHelloSequence(sslSocket *ss) return rv; /* err code is set. */ } - ss->ssl3->hs.ws = (ss->requestCertificate) ? wait_client_cert + ss->ssl3.hs.ws = (ss->opt.requestCertificate) ? wait_client_cert : wait_client_key; return SECSuccess; } @@ -5518,7 +5013,6 @@ static SECStatus ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) { sslSessionID * sid = NULL; - ssl3State * ssl3; PRInt32 tmp; unsigned int i; int j; @@ -5535,8 +5029,8 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) SSL_TRC(3, ("%d: SSL3[%d]: handle client_hello handshake", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); /* Get peer name of client */ rv = ssl_GetPeerInfo(ss); @@ -5548,10 +5042,9 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) if (rv != SECSuccess) { return rv; /* ssl3_InitState has set the error code. */ } - ssl3 = ss->ssl3; - if ((ssl3->hs.ws != wait_client_hello) && - (ssl3->hs.ws != idle_handshake)) { + if ((ss->ssl3.hs.ws != wait_client_hello) && + (ss->ssl3.hs.ws != idle_handshake)) { desc = unexpected_message; errCode = SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO; goto alert_loser; @@ -5570,7 +5063,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) /* grab the client random data. */ rv = ssl3_ConsumeHandshake( - ss, &ssl3->hs.client_random, SSL3_RANDOM_LENGTH, &b, &length); + ss, &ss->ssl3.hs.client_random, SSL3_RANDOM_LENGTH, &b, &length); if (rv != SECSuccess) { goto loser; /* malformed */ } @@ -5581,7 +5074,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) goto loser; /* malformed */ } - if (sidBytes.len > 0 && !ss->noCache) { + if (sidBytes.len > 0 && !ss->opt.noCache) { SSL_TRC(7, ("%d: SSL3[%d]: server, lookup client session-id for 0x%08x%08x%08x%08x", SSL_GETPID(), ss->fd, ss->sec.ci.peer.pr_s6_addr32[0], ss->sec.ci.peer.pr_s6_addr32[1], @@ -5595,7 +5088,6 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) goto loser; } } - SECITEM_FreeItem(&sidBytes, PR_FALSE); /* grab the list of cipher suites. */ rv = ssl3_ConsumeHandshakeVariable(ss, &suites, 2, &b, &length); @@ -5623,10 +5115,10 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) * and this is the first handshake on this connection (not a redo), * then drop this old cache entry and start a new session. */ - if ((sid->peerCert == NULL) && ss->requestCertificate && - ((ss->requireCertificate == SSL_REQUIRE_ALWAYS) || - (ss->requireCertificate == SSL_REQUIRE_NO_ERROR) || - ((ss->requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE) + if ((sid->peerCert == NULL) && ss->opt.requestCertificate && + ((ss->opt.requireCertificate == SSL_REQUIRE_ALWAYS) || + (ss->opt.requireCertificate == SSL_REQUIRE_NO_ERROR) || + ((ss->opt.requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE) && !ss->firstHsDone))) { ++ssl3stats.hch_sid_cache_not_ok; @@ -5654,15 +5146,15 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } if (!j) break; - if (!config_match(suite, ssl3->policy, PR_TRUE)) + if (!config_match(suite, ss->ssl3.policy, PR_TRUE)) break; for (i = 0; i < suites.len; i += 2) { if ((suites.data[i] == MSB(suite->cipher_suite)) && (suites.data[i + 1] == LSB(suite->cipher_suite))) { - ssl3->hs.cipher_suite = suite->cipher_suite; - ssl3->hs.suite_def = - ssl_LookupCipherSuiteDef(ssl3->hs.cipher_suite); + ss->ssl3.hs.cipher_suite = suite->cipher_suite; + ss->ssl3.hs.suite_def = + ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite); goto suite_found; } } @@ -5674,15 +5166,15 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) */ for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) { ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j]; - if (!config_match(suite, ssl3->policy, PR_TRUE)) + if (!config_match(suite, ss->ssl3.policy, PR_TRUE)) continue; for (i = 0; i < suites.len; i += 2) { if ((suites.data[i] == MSB(suite->cipher_suite)) && (suites.data[i + 1] == LSB(suite->cipher_suite))) { - ssl3->hs.cipher_suite = suite->cipher_suite; - ssl3->hs.suite_def = - ssl_LookupCipherSuiteDef(ssl3->hs.cipher_suite); + ss->ssl3.hs.cipher_suite = suite->cipher_suite; + ss->ssl3.hs.suite_def = + ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite); goto suite_found; } } @@ -5695,7 +5187,8 @@ suite_found: for (i = 0; i < comps.len; i++) { for (j = 0; j < compressionMethodsCount; j++) { if (comps.data[i] == compressions[j]) { - ssl3->hs.compression = (SSL3CompressionMethod)compressions[j]; + ss->ssl3.hs.compression = + (SSL3CompressionMethod)compressions[j]; goto compression_found; } } @@ -5705,9 +5198,7 @@ suite_found: goto alert_loser; compression_found: - PORT_Free(suites.data); suites.data = NULL; - PORT_Free(comps.data); comps.data = NULL; ss->sec.send = ssl3_SendApplicationData; @@ -5717,14 +5208,11 @@ compression_found: * as if the client had sent us no sid to begin with, and make a new one. */ if (sid != NULL) do { - PK11SlotInfo * slot; - PK11SymKey * wrapKey; /* wrapping key */ - SECItem wrappedKey; /* wrapped key */ ssl3CipherSpec *pwSpec; - CK_FLAGS keyFlags = 0; + SECItem wrappedMS; /* wrapped key */ if (sid->version != ss->version || - sid->u.ssl3.cipherSuite != ssl3->hs.cipher_suite) { + sid->u.ssl3.cipherSuite != ss->ssl3.hs.cipher_suite) { break; /* not an error */ } @@ -5739,30 +5227,62 @@ compression_found: /* we need to resurrect the master secret.... */ ssl_GetSpecWriteLock(ss); haveSpecWriteLock = PR_TRUE; - pwSpec = ssl3->pwSpec; + pwSpec = ss->ssl3.pwSpec; + if (sid->u.ssl3.keys.msIsWrapped) { + PK11SymKey * wrapKey; /* wrapping key */ + CK_FLAGS keyFlags = 0; + if (ss->opt.bypassPKCS11) { + /* we cannot restart a non-bypass session in a + ** bypass socket. + */ + break; + } - wrapKey = getWrappingKey(ss, NULL, sid->u.ssl3.exchKeyType, - sid->u.ssl3.masterWrapMech, ss->pkcs11PinArg); - if (!wrapKey) { - /* we have a SID cache entry, but no wrapping key for it??? */ - break; - } + wrapKey = getWrappingKey(ss, NULL, sid->u.ssl3.exchKeyType, + sid->u.ssl3.masterWrapMech, + ss->pkcs11PinArg); + if (!wrapKey) { + /* we have a SID cache entry, but no wrapping key for it??? */ + break; + } - if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */ - keyFlags = CKF_SIGN | CKF_VERIFY; - } + if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */ + keyFlags = CKF_SIGN | CKF_VERIFY; + } - wrappedKey.data = sid->u.ssl3.keys.wrapped_master_secret; - wrappedKey.len = sid->u.ssl3.keys.wrapped_master_secret_len; + wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; + wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; - /* unwrap the master secret. */ - pwSpec->master_secret = - PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech, - NULL, &wrappedKey, CKM_SSL3_MASTER_KEY_DERIVE, - CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags); - PK11_FreeSymKey(wrapKey); - if (pwSpec->master_secret == NULL) { - break; /* not an error */ + /* unwrap the master secret. */ + pwSpec->master_secret = + PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech, + NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE, + CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags); + PK11_FreeSymKey(wrapKey); + if (pwSpec->master_secret == NULL) { + break; /* not an error */ + } + } else if (ss->opt.bypassPKCS11) { + wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; + wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; + memcpy(pwSpec->raw_master_secret, wrappedMS.data, wrappedMS.len); + pwSpec->msItem.data = pwSpec->raw_master_secret; + pwSpec->msItem.len = wrappedMS.len; + } else { + /* We CAN restart a bypass session in a non-bypass socket. */ + /* need to import the raw master secret to session object */ + PK11SlotInfo * slot; + wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; + wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; + slot = PK11_GetInternalSlot(); + pwSpec->master_secret = + PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, + PK11_OriginUnwrap, CKA_ENCRYPT, &wrappedMS, + NULL); + PK11_FreeSlot(slot); + if (pwSpec->master_secret == NULL) { + break; /* not an error */ + } } ss->sec.ci.sid = sid; if (sid->peerCert != NULL) { @@ -5775,7 +5295,7 @@ compression_found: * XXX make sure compression still matches */ ++ssl3stats.hch_sid_cache_hits; - ssl3->hs.isResuming = PR_TRUE; + ss->ssl3.hs.isResuming = PR_TRUE; ss->sec.authAlgorithm = sid->authAlgorithm; ss->sec.authKeyBits = sid->authKeyBits; @@ -5798,74 +5318,6 @@ compression_found: goto loser; } - /* reload the FORTEZZA key material. - * On Fortezza, the following keys & IVs are generated by the KEA, - * not from the PMS. Since we're not going to redo the KEA, we - * have to save & restore them for Fortezza. - * use kea because we haven't call InitCipher Specs yet...? - */ - if (ssl3->hs.suite_def->bulk_cipher_alg == cipher_fortezza) { - PK11SymKey * Ks; - SECItem item; - - PORT_Memcpy(pwSpec->client.write_iv, - sid->u.ssl3.keys.client_write_iv, - sizeof sid->u.ssl3.keys.client_write_iv); - PORT_Memcpy(pwSpec->server.write_iv, - sid->u.ssl3.keys.server_write_iv, - sizeof sid->u.ssl3.keys.server_write_iv); - - /* Now, unwrap the client and server write keys with Ks */ - - /* get the slot that the fortezza server private key is in. */ - slot = PK11_GetSlotFromPrivateKey( - ss->serverCerts[kt_fortezza].serverKey); - if (slot == NULL) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto loser; - } - - /* Look up the Token Fixed Key */ - Ks = PK11_FindFixedKey(slot, CKM_SKIPJACK_WRAP, NULL, - ss->pkcs11PinArg); - PK11_FreeSlot(slot); - if (Ks == NULL) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto loser; - } - - /* unwrap client write key with the local Ks */ - item.data = sid->u.ssl3.keys.wrapped_client_write_key; - item.len = sizeof sid->u.ssl3.keys.wrapped_client_write_key; - - pwSpec->client.write_key = - PK11_UnwrapSymKey(Ks, CKM_SKIPJACK_WRAP, NULL, &item, - CKM_SKIPJACK_CBC64, CKA_DECRYPT, 0); - if (pwSpec->client.write_key == NULL) { - SEND_ALERT - ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_UNWRAP_FAILURE); - goto loser; - } - - /* unwrap server write key with the local Ks */ - item.data = sid->u.ssl3.keys.wrapped_server_write_key; - item.len = sizeof sid->u.ssl3.keys.wrapped_server_write_key; - - pwSpec->server.write_key = - PK11_UnwrapSymKey(Ks, CKM_SKIPJACK_WRAP, NULL, &item, - CKM_SKIPJACK_CBC64, CKA_ENCRYPT, 0); - if (pwSpec->server.write_key == NULL) { - PK11_FreeSymKey(pwSpec->client.write_key); - pwSpec->client.write_key = NULL; - SEND_ALERT - ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_UNWRAP_FAILURE); - goto loser; - } - /* Set flag that says "generate 8 byte random prefix plaintext." */ - PK11_SetFortezzaHack(pwSpec->server.write_key); /* can't fail */ - - } - if (haveSpecWriteLock) { ssl_ReleaseSpecWriteLock(ss); haveSpecWriteLock = PR_FALSE; @@ -5884,7 +5336,7 @@ compression_found: goto loser; } rv = ssl3_SendFinished(ss, 0); - ssl3->hs.ws = wait_change_cipher; + ss->ssl3.hs.ws = wait_change_cipher; if (rv != SECSuccess) { errCode = PORT_GetError(); goto loser; @@ -5918,7 +5370,7 @@ compression_found: } ss->sec.ci.sid = sid; - ssl3->hs.isResuming = PR_FALSE; + ss->ssl3.hs.isResuming = PR_FALSE; ssl_GetXmitBufLock(ss); rv = ssl3_SendServerHelloSequence(ss); ssl_ReleaseXmitBufLock(ss); @@ -5947,10 +5399,6 @@ loser: haveSpecWriteLock = PR_FALSE; } - if (sidBytes.data != NULL) SECITEM_FreeItem(&sidBytes, PR_FALSE); - if (suites.data != NULL) SECITEM_FreeItem(&suites, PR_FALSE); - if (comps.data != NULL) SECITEM_FreeItem(&comps, PR_FALSE); - if (haveXmitBufLock) { ssl_ReleaseXmitBufLock(ss); haveXmitBufLock = PR_FALSE; @@ -5983,7 +5431,7 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length) SSL_TRC(3, ("%d: SSL3[%d]: handle v2 client_hello", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); ssl_GetSSL3HandshakeLock(ss); @@ -5993,7 +5441,7 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length) return rv; /* ssl3_InitState has set the error code. */ } - if (ss->ssl3->hs.ws != wait_client_hello) { + if (ss->ssl3.hs.ws != wait_client_hello) { desc = unexpected_message; errCode = SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO; goto loser; /* alert_loser */ @@ -6033,12 +5481,12 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length) PORT_Assert(SSL_MAX_CHALLENGE_BYTES == SSL3_RANDOM_LENGTH); - PORT_Memset(&ss->ssl3->hs.client_random, 0, SSL3_RANDOM_LENGTH); + PORT_Memset(&ss->ssl3.hs.client_random, 0, SSL3_RANDOM_LENGTH); PORT_Memcpy( - &ss->ssl3->hs.client_random.rand[SSL3_RANDOM_LENGTH - rand_length], + &ss->ssl3.hs.client_random.rand[SSL3_RANDOM_LENGTH - rand_length], random, rand_length); - PRINT_BUF(60, (ss, "client random:", &ss->ssl3->hs.client_random.rand[0], + PRINT_BUF(60, (ss, "client random:", &ss->ssl3.hs.client_random.rand[0], SSL3_RANDOM_LENGTH)); i = ssl3_config_match_init(ss); @@ -6053,16 +5501,16 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length) */ for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) { ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j]; - if (!config_match(suite, ss->ssl3->policy, PR_TRUE)) + if (!config_match(suite, ss->ssl3.policy, PR_TRUE)) continue; for (i = 0; i < suite_length; i += 3) { if ((suites[i] == 0) && (suites[i+1] == MSB(suite->cipher_suite)) && (suites[i+2] == LSB(suite->cipher_suite))) { - ss->ssl3->hs.cipher_suite = suite->cipher_suite; - ss->ssl3->hs.suite_def = - ssl_LookupCipherSuiteDef(ss->ssl3->hs.cipher_suite); + ss->ssl3.hs.cipher_suite = suite->cipher_suite; + ss->ssl3.hs.suite_def = + ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite); goto suite_found; } } @@ -6072,7 +5520,7 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length) suite_found: - ss->ssl3->hs.compression = compression_null; + ss->ssl3.hs.compression = compression_null; ss->sec.send = ssl3_SendApplicationData; /* we don't even search for a cache hit here. It's just a miss. */ @@ -6134,8 +5582,8 @@ ssl3_SendServerHello(sslSocket *ss) SSL_TRC(3, ("%d: SSL3[%d]: send server_hello handshake", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveXmitBufLock(ss)); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); PORT_Assert( MSB(ss->version) == MSB(SSL_LIBRARY_VERSION_3_0)); if (MSB(ss->version) != MSB(SSL_LIBRARY_VERSION_3_0)) { @@ -6156,13 +5604,13 @@ ssl3_SendServerHello(sslSocket *ss) if (rv != SECSuccess) { return rv; /* err set by AppendHandshake. */ } - rv = ssl3_GetNewRandom(&ss->ssl3->hs.server_random); + rv = ssl3_GetNewRandom(&ss->ssl3.hs.server_random); if (rv != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE); return rv; } rv = ssl3_AppendHandshake( - ss, &ss->ssl3->hs.server_random, SSL3_RANDOM_LENGTH); + ss, &ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH); if (rv != SECSuccess) { return rv; /* err set by AppendHandshake. */ } @@ -6176,15 +5624,15 @@ ssl3_SendServerHello(sslSocket *ss) return rv; /* err set by AppendHandshake. */ } - rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3->hs.cipher_suite, 2); + rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.cipher_suite, 2); if (rv != SECSuccess) { return rv; /* err set by AppendHandshake. */ } - rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3->hs.compression, 1); + rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.compression, 1); if (rv != SECSuccess) { return rv; /* err set by AppendHandshake. */ } - rv = ssl3_SetupPendingCipherSpec(ss, ss->ssl3); + rv = ssl3_SetupPendingCipherSpec(ss); if (rv != SECSuccess) { return rv; /* err set by ssl3_SetupPendingCipherSpec */ } @@ -6196,25 +5644,19 @@ ssl3_SendServerHello(sslSocket *ss) static SECStatus ssl3_SendServerKeyExchange(sslSocket *ss) { -const ssl3KEADef * kea_def = ss->ssl3->hs.kea_def; +const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def; SECStatus rv = SECFailure; int length; PRBool isTLS; SECItem signed_hash = {siBuffer, NULL, 0}; SSL3Hashes hashes; SECKEYPublicKey * sdPub; /* public key for step-down */ -#ifdef NSS_ENABLE_ECC - SECKEYPublicKey * ecdhePub; - SECItem ec_params = {siBuffer, NULL, 0}; - ECName curve; - SSL3KEAType certIndex; -#endif /* NSS_ENABLE_ECC */ SSL_TRC(3, ("%d: SSL3[%d]: send server_key_exchange handshake", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveXmitBufLock(ss)); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); switch (kea_def->exchKeyType) { case kt_rsa: @@ -6227,16 +5669,16 @@ const ssl3KEADef * kea_def = ss->ssl3->hs.kea_def; } rv = ssl3_ComputeExportRSAKeyHash(sdPub->u.rsa.modulus, sdPub->u.rsa.publicExponent, - &ss->ssl3->hs.client_random, - &ss->ssl3->hs.server_random, - &hashes); + &ss->ssl3.hs.client_random, + &ss->ssl3.hs.server_random, + &hashes, ss->opt.bypassPKCS11); if (rv != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); return rv; } - isTLS = (PRBool)(ss->ssl3->pwSpec->version > SSL_LIBRARY_VERSION_3_0); - rv = ssl3_SignHashes(&hashes, ss->serverCerts[kt_rsa].serverKey, + isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); + rv = ssl3_SignHashes(&hashes, ss->serverCerts[kt_rsa].SERVERKEY, &signed_hash, isTLS); if (rv != SECSuccess) { goto loser; /* ssl3_SignHashes has set err. */ @@ -6276,112 +5718,11 @@ const ssl3KEADef * kea_def = ss->ssl3->hs.kea_def; PORT_Free(signed_hash.data); return SECSuccess; - case kt_fortezza: - - /* Set server's "random" public key R_s to the email value == 1 */ - PORT_Memset(ss->ssl3->fortezza.R_s, 0, sizeof(ss->ssl3->fortezza.R_s)); - ss->ssl3->fortezza.R_s[127] = 1; - - /* don't waste time signing the random number */ - length = sizeof (ss->ssl3->fortezza.R_s) /*+ 2 + signed_hash.len*/; - - rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length); - if (rv != SECSuccess) { - goto loser; /* err set by AppendHandshake. */ - } - - rv = ssl3_AppendHandshake( ss, &ss->ssl3->fortezza.R_s, - sizeof(ss->ssl3->fortezza.R_s)); - if (rv != SECSuccess) { - goto loser; /* err set by AppendHandshake. */ - } - return SECSuccess; - #ifdef NSS_ENABLE_ECC - case kt_ecdh: - /* Generate ephemeral ECDH key pair and send the public key */ - rv = ssl3_CreateECDHEphemeralKeys(ss); - if (rv != SECSuccess) { - goto loser; /* err set by AppendHandshake. */ - } - ecdhePub = ss->ephemeralECDHKeyPair->pubKey; - PORT_Assert(ecdhePub != NULL); - if (!ecdhePub) { - PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); - return SECFailure; - } - - ec_params.len = 2; - ec_params.data = (unsigned char*)PORT_Alloc(ec_params.len); - curve = params2ecName(&ecdhePub->u.ec.DEREncodedParams); - if (curve != ec_noName) { - ec_params.data[0] = ec_type_named; - ec_params.data[1] = curve; - } else { - PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); - goto loser; - } - - rv = ssl3_ComputeECDHKeyHash(ec_params, ecdhePub->u.ec.publicValue, - &ss->ssl3->hs.client_random, - &ss->ssl3->hs.server_random, - &hashes); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); - goto loser; - } - - isTLS = (PRBool)(ss->ssl3->pwSpec->version > SSL_LIBRARY_VERSION_3_0); - - /* XXX SSLKEAType isn't really a good choice for - * indexing certificates but that's all we have - * for now. - */ - if (kea_def->kea == kea_ecdhe_rsa) - certIndex = kt_rsa; - else /* kea_def->kea == kea_ecdhe_ecdsa */ - certIndex = kt_ecdh; - - rv = ssl3_SignHashes(&hashes, ss->serverCerts[certIndex].serverKey, - &signed_hash, isTLS); - if (rv != SECSuccess) { - goto loser; /* ssl3_SignHashes has set err. */ - } - if (signed_hash.data == NULL) { - /* how can this happen and rv == SECSuccess ?? */ - PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); - goto loser; - } - - length = ec_params.len + - 1 + ecdhePub->u.ec.publicValue.len + - 2 + signed_hash.len; - - rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length); - if (rv != SECSuccess) { - goto loser; /* err set by AppendHandshake. */ - } - - rv = ssl3_AppendHandshake(ss, ec_params.data, ec_params.len); - if (rv != SECSuccess) { - goto loser; /* err set by AppendHandshake. */ - } - - rv = ssl3_AppendHandshakeVariable(ss, ecdhePub->u.ec.publicValue.data, - ecdhePub->u.ec.publicValue.len, 1); - if (rv != SECSuccess) { - goto loser; /* err set by AppendHandshake. */ - } - - rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data, - signed_hash.len, 2); - if (rv != SECSuccess) { - goto loser; /* err set by AppendHandshake. */ - } - - PORT_Free(ec_params.data); - PORT_Free(signed_hash.data); - return SECSuccess; + case kt_ecdh: { + rv = ssl3_SendECDHServerKeyExchange(ss); + return rv; + } #endif /* NSS_ENABLE_ECC */ case kt_dh: @@ -6391,10 +5732,6 @@ const ssl3KEADef * kea_def = ss->ssl3->hs.kea_def; break; } loser: -#ifdef NSS_ENABLE_ECC - if (ec_params.data != NULL) - PORT_Free(ec_params.data); -#endif /* NSS_ENABLE_ECC */ if (signed_hash.data != NULL) PORT_Free(signed_hash.data); return SECFailure; @@ -6418,11 +5755,11 @@ const uint8 * certTypes; SSL_TRC(3, ("%d: SSL3[%d]: send certificate_request handshake", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveXmitBufLock(ss)); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); - /* ssl3->ca_list is initialized to NULL, and never changed. */ - ca_list = ss->ssl3->ca_list; + /* ssl3.ca_list is initialized to NULL, and never changed. */ + ca_list = ss->ssl3.ca_list; if (!ca_list) { ca_list = ssl3_server_ca_list; } @@ -6441,13 +5778,8 @@ const uint8 * certTypes; calen += 2 + name->len; } - if (ss->ssl3->hs.kea_def->exchKeyType == kt_fortezza) { - certTypes = fortezza_certificate_types; - certTypesLength = sizeof fortezza_certificate_types; - } else { - certTypes = certificate_types; - certTypesLength = sizeof certificate_types; - } + certTypes = certificate_types; + certTypesLength = sizeof certificate_types; length = 1 + certTypesLength + 2 + calen; @@ -6481,8 +5813,8 @@ ssl3_SendServerHelloDone(sslSocket *ss) SSL_TRC(3, ("%d: SSL3[%d]: send server_hello_done handshake", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveXmitBufLock(ss)); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); rv = ssl3_AppendHandshakeHeader(ss, server_hello_done, 0); if (rv != SECSuccess) { @@ -6511,10 +5843,10 @@ ssl3_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length, SSL_TRC(3, ("%d: SSL3[%d]: handle certificate_verify handshake", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); - if (ss->ssl3->hs.ws != wait_cert_verify || ss->sec.peerCert == NULL) { + if (ss->ssl3.hs.ws != wait_cert_verify || ss->sec.peerCert == NULL) { desc = unexpected_message; errCode = SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY; goto alert_loser; @@ -6525,7 +5857,7 @@ ssl3_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length, goto loser; /* malformed. */ } - isTLS = (PRBool)(ss->ssl3->prSpec->version > SSL_LIBRARY_VERSION_3_0); + isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0); /* XXX verify that the key & kea match */ rv = ssl3_VerifySignedHashes(hashes, ss->sec.peerCert, &signed_hash, @@ -6536,281 +5868,29 @@ ssl3_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length, goto alert_loser; } - PORT_Free(signed_hash.data); signed_hash.data = NULL; if (length != 0) { desc = isTLS ? decode_error : illegal_parameter; goto alert_loser; /* malformed */ } - ss->ssl3->hs.ws = wait_change_cipher; + ss->ssl3.hs.ws = wait_change_cipher; return SECSuccess; alert_loser: SSL3_SendAlert(ss, alert_fatal, desc); loser: - if (signed_hash.data != NULL) SECITEM_FreeItem(&signed_hash, PR_FALSE); PORT_SetError(errCode); return SECFailure; } -/* -** Called from ssl3_HandleClientKeyExchange() -*/ -static SECStatus -ssl3_HandleFortezzaClientKeyExchange(sslSocket *ss, SSL3Opaque *b, - PRUint32 length, - SECKEYPrivateKey *serverKey) -{ - SECKEYPublicKey * pubKey = NULL; - PK11SymKey * tek = NULL; - PK11SymKey * pms; - PK11SymKey * Ks = NULL; - sslSessionID * sid = ss->sec.ci.sid; - ssl3CipherSpec * pwSpec = ss->ssl3->pwSpec; - void * pwArg = ss->pkcs11PinArg; - SECStatus rv; - SECItem raItem; - SECItem rbItem; - SECItem param; - SECItem item; - SECItem enc_pms; - SSL3FortezzaKeys fortezza_CKE; - - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); - - fortezza_CKE.y_c.data = NULL; - rv = ssl3_ConsumeHandshakeVariable(ss, &fortezza_CKE.y_c, 1, &b, &length); - if (rv != SECSuccess) { - PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH); - goto fortezza_loser; - } - rv = ssl3_ConsumeHandshake(ss, &fortezza_CKE.r_c, - sizeof fortezza_CKE - sizeof fortezza_CKE.y_c, - &b, &length); - if (rv != SECSuccess) { - PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH); - goto fortezza_loser; - } - - /* Build a Token Encryption key (tek). TEK's can never be unloaded - * from the card, but given these parameters, and *OUR* fortezza - * card, we can always regenerate the same one on the fly. - */ - if (ss->sec.peerCert != NULL) { - /* client-auth case */ - - pubKey = CERT_ExtractPublicKey(ss->sec.peerCert); - if (pubKey == NULL) { - SEND_ALERT - PORT_SetError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE); - rv = SECFailure; - goto fortezza_loser; - } - - if (pubKey->keyType != fortezzaKey) { - /* handle V3 client-auth case */ - SECItem sigItem; - SECItem hashItem; - unsigned char hash[SHA1_LENGTH]; - - rv = ssl3_ComputeFortezzaPublicKeyHash(fortezza_CKE.y_c, hash); - if (rv != SECSuccess) { - SEND_ALERT - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto fortezza_loser; - } - sigItem.data = fortezza_CKE.y_signature; - sigItem.len = sizeof fortezza_CKE.y_signature; - - hashItem.data = hash; - hashItem.len = sizeof hash; - - rv = PK11_Verify(pubKey, &sigItem, &hashItem, pwArg); - if (rv != SECSuccess) { - SSL3_SendAlert(ss, alert_fatal, illegal_parameter); - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto fortezza_loser; - } - SECKEY_DestroyPublicKey(pubKey); pubKey = NULL; - } - } - rv = SECFailure; - - /* Make the public key if necessary */ - if (fortezza_CKE.y_c.len != 0) { - if (pubKey != NULL) { - /* The client is not allowed to send the public key - * if it can be extracted from the certificate. */ - SSL3_SendAlert(ss, alert_fatal, illegal_parameter); - PORT_SetError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto fortezza_loser; - } - pubKey = PK11_MakeKEAPubKey(fortezza_CKE.y_c.data, - fortezza_CKE.y_c.len); - } - if (pubKey == NULL) { - /* no public Key in either the cert or the protocol message*/ - SSL3_SendAlert(ss, alert_fatal, illegal_parameter); - PORT_SetError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto fortezza_loser; - } - - /* Now we derive the TEK. r_c is the client's "random" public key. */ - raItem.data = fortezza_CKE.r_c; - raItem.len = sizeof(fortezza_CKE.r_c); - - /* R_s == server's "random" public key, sent in the Server Key Exchange */ - rbItem.data = ss->ssl3->fortezza.R_s; - rbItem.len = sizeof ss->ssl3->fortezza.R_s; - - tek = PK11_PubDerive(serverKey, pubKey, PR_FALSE, /* don't gen r_c */ - &raItem, &rbItem, CKM_KEA_KEY_DERIVE, - CKM_SKIPJACK_WRAP, CKA_WRAP, 0, pwArg); - SECKEY_DestroyPublicKey(pubKey); pubKey = NULL; - if (tek == NULL) { - SEND_ALERT - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto fortezza_loser; - } - - ss->ssl3->fortezza.tek = PK11_ReferenceSymKey(tek); - - if (pwSpec->cipher_def->calg == calg_fortezza) { - item.data = fortezza_CKE.wrapped_client_write_key; - item.len = sizeof fortezza_CKE.wrapped_client_write_key; - - pwSpec->client.write_key = - PK11_UnwrapSymKey(tek, CKM_SKIPJACK_WRAP, NULL, &item, - CKM_SKIPJACK_CBC64, CKA_DECRYPT, 0); - if (pwSpec->client.write_key == NULL) { - SEND_ALERT - ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_UNWRAP_FAILURE); - goto fortezza_loser; - } - - item.data = fortezza_CKE.wrapped_server_write_key; - item.len = sizeof fortezza_CKE.wrapped_server_write_key; - - pwSpec->server.write_key = - PK11_UnwrapSymKey(tek, CKM_SKIPJACK_WRAP, NULL, &item, - CKM_SKIPJACK_CBC64, CKA_ENCRYPT, 0); - if (pwSpec->server.write_key == NULL) { - PK11_FreeSymKey(pwSpec->client.write_key); - pwSpec->client.write_key = NULL; - SEND_ALERT - ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_UNWRAP_FAILURE); - goto fortezza_loser; - } - /* Set a flag that says "generate 8 byte random prefix plaintext." */ - PK11_SetFortezzaHack(pwSpec->server.write_key); /* can't fail */ - - PORT_Memcpy(pwSpec->client.write_iv, fortezza_CKE.client_write_iv, - sizeof fortezza_CKE.client_write_iv); - PORT_Memcpy(pwSpec->server.write_iv, fortezza_CKE.server_write_iv, - sizeof fortezza_CKE.server_write_iv); - - } - - /* decrypt the pms with the TEK */ - enc_pms.data = fortezza_CKE.encrypted_preMasterSecret; - enc_pms.len = sizeof fortezza_CKE.encrypted_preMasterSecret; - - param.data = fortezza_CKE.master_secret_iv; - param.len = sizeof fortezza_CKE.master_secret_iv; - - pms = PK11_UnwrapSymKey(tek, CKM_SKIPJACK_CBC64, ¶m, &enc_pms, - CKM_SSL3_MASTER_KEY_DERIVE, CKA_DERIVE, 0); - if (pms == NULL) { - SEND_ALERT - ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_UNWRAP_FAILURE); - goto fortezza_loser; - } - - rv = ssl3_InitPendingCipherSpec(ss, pms); - PK11_FreeSymKey(pms); - if (rv != SECSuccess) { - SEND_ALERT - goto fortezza_loser; /* err code is set. */ - } - - if (pwSpec->cipher_def->calg == calg_fortezza) { - PK11SlotInfo * slot; - - sid->u.ssl3.clientWriteKey = - PK11_ReferenceSymKey(pwSpec->client.write_key); - sid->u.ssl3.serverWriteKey = - PK11_ReferenceSymKey(pwSpec->server.write_key); - - PORT_Memcpy(sid->u.ssl3.keys.client_write_iv, pwSpec->client.write_iv, - sizeof sid->u.ssl3.keys.client_write_iv); - PORT_Memcpy(sid->u.ssl3.keys.server_write_iv, pwSpec->server.write_iv, - sizeof sid->u.ssl3.keys.server_write_iv); - - /* Now, wrap the client and server write keys in Ks for storage - * in the on-disk sid. - */ - - slot = PK11_GetSlotFromKey(tek); /* get ref to the slot */ - if (slot == NULL) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto fortezza_loser; - } - - /* Look up the Token Fixed Key */ - Ks = PK11_FindFixedKey(slot, CKM_SKIPJACK_WRAP, NULL, ss->pkcs11PinArg); - PK11_FreeSlot(slot); - if (Ks == NULL) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto fortezza_loser; - } - - /* rewrap server write key with the local Ks */ - item.data = sid->u.ssl3.keys.wrapped_server_write_key; - item.len = sizeof sid->u.ssl3.keys.wrapped_server_write_key; - rv = PK11_WrapSymKey(CKM_SKIPJACK_WRAP, NULL, Ks, - pwSpec->server.write_key, &item); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto fortezza_loser; - } - - /* rewrap client write key with the local Ks */ - item.data = sid->u.ssl3.keys.wrapped_client_write_key; - item.len = sizeof sid->u.ssl3.keys.wrapped_client_write_key; - rv = PK11_WrapSymKey(CKM_SKIPJACK_WRAP, NULL, Ks, - pwSpec->client.write_key, &item); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - goto fortezza_loser; - } - - /* wrap the master secret later, when we handle the client's - * finished message. - */ - } - - sid->u.ssl3.hasFortezza = PR_TRUE; - sid->u.ssl3.tek = tek; tek = NULL; - - rv = SECSuccess; - -fortezza_loser: - if (Ks) PK11_FreeSymKey(Ks); - if (tek) PK11_FreeSymKey(tek); - if (pubKey) SECKEY_DestroyPublicKey(pubKey); - if (fortezza_CKE.y_c.data != NULL) - SECITEM_FreeItem(&fortezza_CKE.y_c, PR_FALSE); - return rv; -} /* find a slot that is able to generate a PMS and wrap it with RSA. * Then generate and return the PMS. * If the serverKeySlot parameter is non-null, this function will use * that slot to do the job, otherwise it will find a slot. * - * Called from ssl3_GenerateSessionKeys() (above) + * Called from ssl3_DeriveConnectionKeysPKCS11() (above) * sendRSAClientKeyExchange() (above) * ssl3_HandleRSAClientKeyExchange() (below) * Caller must hold the SpecWriteLock, the SSL3HandshakeLock @@ -6826,7 +5906,7 @@ ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, CK_VERSION version; CK_MECHANISM_TYPE mechanism_array[3]; - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); if (slot == NULL) { SSLCipherAlgorithm calg; @@ -6834,8 +5914,8 @@ ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, ** read locks. Also, all the callers who call with a non-null ** slot already hold the SpecWriteLock. */ - PORT_Assert( ssl_HaveSpecWriteLock(ss)); - PORT_Assert(ss->ssl3->prSpec == ss->ssl3->pwSpec); + PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); + PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); calg = spec->cipher_def->calg; PORT_Assert(alg2Mech[calg].calg == calg); @@ -6891,16 +5971,23 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss, SECKEYPrivateKey *serverKey) { PK11SymKey * pms; + unsigned char * cr = (unsigned char *)&ss->ssl3.hs.client_random; + unsigned char * sr = (unsigned char *)&ss->ssl3.hs.server_random; + ssl3CipherSpec * pwSpec = ss->ssl3.pwSpec; + unsigned int outLen = 0; + PRBool isTLS = PR_FALSE; SECStatus rv; SECItem enc_pms; + unsigned char rsaPmsBuf[SSL3_RSA_PMS_LENGTH]; + SECItem pmsItem = {siBuffer, rsaPmsBuf, sizeof rsaPmsBuf}; - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); enc_pms.data = b; enc_pms.len = length; - if (ss->ssl3->prSpec->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */ + if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */ PRInt32 kLen; kLen = ssl3_ConsumeHandshakeNumber(ss, 2, &enc_pms.data, &enc_pms.len); if (kLen < 0) { @@ -6910,114 +5997,83 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss, if ((unsigned)kLen < enc_pms.len) { enc_pms.len = kLen; } - } - /* - * decrypt pms out of the incoming buffer - * Note: CKM_SSL3_PRE_MASTER_KEY_GEN is NOT the mechanism used to do - * the unwrap. Rather, it is the mechanism with which the unwrapped - * pms will be used. - */ - pms = PK11_PubUnwrapSymKey(serverKey, &enc_pms, - CKM_SSL3_PRE_MASTER_KEY_GEN, CKA_DERIVE, 0); - if (pms != NULL) { - PRINT_BUF(60, (ss, "decrypted premaster secret:", - PK11_GetKeyData(pms)->data, - PK11_GetKeyData(pms)->len)); + isTLS = PR_TRUE; } else { - /* unwrap failed. Generate a bogus pre-master secret and carry on. */ - PK11SlotInfo * slot = PK11_GetSlotFromPrivateKey(serverKey); - - ssl_GetSpecWriteLock(ss); - pms = ssl3_GenerateRSAPMS(ss, ss->ssl3->prSpec, slot); - ssl_ReleaseSpecWriteLock(ss); - - PK11_FreeSlot(slot); - } - - if (pms == NULL) { - /* last gasp. */ - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - return SECFailure; - } - - rv = ssl3_InitPendingCipherSpec(ss, pms); - PK11_FreeSymKey(pms); - if (rv != SECSuccess) { - SEND_ALERT - return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */ + isTLS = (PRBool)(ss->ssl3.hs.kea_def->tls_keygen != 0); } - return SECSuccess; -} -#ifdef NSS_ENABLE_ECC -/* -** Called from ssl3_HandleClientKeyExchange() -*/ -static SECStatus -ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b, - PRUint32 length, - SECKEYPublicKey *srvrPubKey, - SECKEYPrivateKey *srvrPrivKey) -{ - PK11SymKey * pms; - SECStatus rv; - SECKEYPublicKey clntPubKey; - CK_MECHANISM_TYPE target; - PRBool isTLS; - CK_EC_KDF_TYPE kdf; - - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); - - clntPubKey.keyType = ecKey; - clntPubKey.u.ec.DEREncodedParams.len = - srvrPubKey->u.ec.DEREncodedParams.len; - clntPubKey.u.ec.DEREncodedParams.data = - srvrPubKey->u.ec.DEREncodedParams.data; - - rv = ssl3_ConsumeHandshakeVariable(ss, &clntPubKey.u.ec.publicValue, - 1, &b, &length); - if (rv != SECSuccess) { - SEND_ALERT - return SECFailure; /* XXX Who sets the error code?? */ - } - - isTLS = (PRBool)(ss->ssl3->prSpec->version > SSL_LIBRARY_VERSION_3_0); - - if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH; - else target = CKM_SSL3_MASTER_KEY_DERIVE_DH; + if (ss->opt.bypassPKCS11) { + /* TRIPLE BYPASS, get PMS directly from RSA decryption. + * Use PK11_PrivDecryptPKCS1 to decrypt the PMS to a buffer, + * then, check for version rollback attack, then + * do the equivalent of ssl3_DeriveMasterSecret, placing the MS in + * pwSpec->msItem. Finally call ssl3_InitPendingCipherSpec with + * ss and NULL, so that it will use the MS we've already derived here. + */ - /* If field size is not more than 24 octets, then use SHA-1 hash of result; - * otherwise, use result (see section 4.8 of draft-ietf-tls-ecc-03.txt). - */ - if (srvrPubKey->u.ec.size <= 24 * 8) { - kdf = CKD_SHA1_KDF; + rv = PK11_PrivDecryptPKCS1(serverKey, rsaPmsBuf, &outLen, + sizeof rsaPmsBuf, enc_pms.data, enc_pms.len); + if (rv != SECSuccess) { + /* avoid Bleichenbacker attack. generate faux pms. */ + rv = PK11_GenerateRandom(rsaPmsBuf, sizeof rsaPmsBuf); + /* ignore failure */ + } else if (ss->opt.detectRollBack) { + SSL3ProtocolVersion client_version = + (rsaPmsBuf[0] << 8) | rsaPmsBuf[1]; + if (client_version != ss->clientHelloVersion) { + /* Version roll-back detected. ensure failure. */ + rv = PK11_GenerateRandom(rsaPmsBuf, sizeof rsaPmsBuf); + } + } + /* have PMS, build MS without PKCS11 */ + rv = ssl3_MasterKeyDeriveBypass(pwSpec, cr, sr, &pmsItem, isTLS, + PR_TRUE); + if (rv != SECSuccess) { + pwSpec->msItem.data = pwSpec->raw_master_secret; + pwSpec->msItem.len = SSL3_MASTER_SECRET_LENGTH; + PK11_GenerateRandom(pwSpec->msItem.data, pwSpec->msItem.len); + } + rv = ssl3_InitPendingCipherSpec(ss, NULL); } else { - kdf = CKD_NULL; - } + /* + * unwrap pms out of the incoming buffer + * Note: CKM_SSL3_MASTER_KEY_DERIVE is NOT the mechanism used to do + * the unwrap. Rather, it is the mechanism with which the + * unwrapped pms will be used. + */ + pms = PK11_PubUnwrapSymKey(serverKey, &enc_pms, + CKM_SSL3_MASTER_KEY_DERIVE, CKA_DERIVE, 0); + if (pms != NULL) { + PRINT_BUF(60, (ss, "decrypted premaster secret:", + PK11_GetKeyData(pms)->data, + PK11_GetKeyData(pms)->len)); + } else { + /* unwrap failed. Generate a bogus PMS and carry on. */ + PK11SlotInfo * slot = PK11_GetSlotFromPrivateKey(serverKey); - /* Determine the PMS */ - pms = PK11_PubDeriveWithKDF(srvrPrivKey, &clntPubKey, PR_FALSE, NULL, NULL, - CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0, - kdf, NULL, NULL); + ssl_GetSpecWriteLock(ss); + pms = ssl3_GenerateRSAPMS(ss, ss->ssl3.prSpec, slot); + ssl_ReleaseSpecWriteLock(ss); + PK11_FreeSlot(slot); + } - PORT_Free(clntPubKey.u.ec.publicValue.data); + if (pms == NULL) { + /* last gasp. */ + ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); + return SECFailure; + } - if (pms == NULL) { - /* last gasp. */ - ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); - return SECFailure; + rv = ssl3_InitPendingCipherSpec(ss, pms); + PK11_FreeSymKey(pms); } - rv = ssl3_InitPendingCipherSpec(ss, pms); - PK11_FreeSymKey(pms); if (rv != SECSuccess) { SEND_ALERT - return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */ + return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */ } return SECSuccess; } -#endif /* NSS_ENABLE_ECC */ + /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete * ssl3 ClientKeyExchange message from the remote client @@ -7036,16 +6092,16 @@ const ssl3KEADef * kea_def; SSL_TRC(3, ("%d: SSL3[%d]: handle client_key_exchange handshake", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); - if (ss->ssl3->hs.ws != wait_client_key) { + if (ss->ssl3.hs.ws != wait_client_key) { SSL3_SendAlert(ss, alert_fatal, unexpected_message); PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH); return SECFailure; } - kea_def = ss->ssl3->hs.kea_def; + kea_def = ss->ssl3.hs.kea_def; #ifdef NSS_ENABLE_ECC /* XXX Using SSLKEAType to index server certifiates @@ -7064,16 +6120,16 @@ const ssl3KEADef * kea_def; } else { #endif /* NSS_ENABLE_ECC */ - serverKey = (ss->ssl3->hs.usedStepDownKey + serverKey = (ss->ssl3.hs.usedStepDownKey #ifdef DEBUG && kea_def->is_limited /* XXX OR cert is signing only */ && kea_def->exchKeyType == kt_rsa && ss->stepDownKeyPair != NULL #endif ) ? ss->stepDownKeyPair->privKey - : ss->serverCerts[kea_def->exchKeyType].serverKey; + : ss->serverCerts[kea_def->exchKeyType].SERVERKEY; - if (ss->ssl3->hs.usedStepDownKey + if (ss->ssl3.hs.usedStepDownKey #ifdef DEBUG && kea_def->is_limited /* XXX OR cert is signing only */ && kea_def->exchKeyType == kt_rsa @@ -7084,7 +6140,7 @@ const ssl3KEADef * kea_def; ss->sec.keaKeyBits = EXPORT_RSA_KEY_LENGTH * BPB; } else { sslServerCerts * sc = ss->serverCerts + kea_def->exchKeyType; - serverKey = sc->serverKey; + serverKey = sc->SERVERKEY; ss->sec.keaKeyBits = sc->serverKeyBits; } @@ -7105,17 +6161,11 @@ const ssl3KEADef * kea_def; rv = ssl3_HandleRSAClientKeyExchange(ss, b, length, serverKey); if (rv != SECSuccess) { SEND_ALERT - return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */ - } - break; - - case kt_fortezza: - rv = ssl3_HandleFortezzaClientKeyExchange(ss, b, length, serverKey); - if (rv != SECSuccess) { return SECFailure; /* error code set */ } break; + #ifdef NSS_ENABLE_ECC case kt_ecdh: /* XXX We really ought to be able to store multiple @@ -7150,7 +6200,7 @@ const ssl3KEADef * kea_def; PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); return SECFailure; } - ss->ssl3->hs.ws = ss->sec.peerCert ? wait_cert_verify : wait_change_cipher; + ss->ssl3.hs.ws = ss->sec.peerCert ? wait_cert_verify : wait_change_cipher; return SECSuccess; } @@ -7250,8 +6300,8 @@ ssl3_SendCertificate(sslSocket *ss) SSL_TRC(3, ("%d: SSL3[%d]: send certificate handshake", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveXmitBufLock(ss)); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); if (ss->sec.localCert) CERT_DestroyCertificate(ss->sec.localCert); @@ -7266,20 +6316,20 @@ ssl3_SendCertificate(sslSocket *ss) * for ECDHE-ECDSA or client-side authentication * using EC certificates. */ - if ((ss->ssl3->hs.kea_def->kea == kea_ecdhe_rsa) || - (ss->ssl3->hs.kea_def->kea == kea_dhe_rsa)) { + if ((ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) || + (ss->ssl3.hs.kea_def->kea == kea_dhe_rsa)) { certIndex = kt_rsa; } else { - certIndex = ss->ssl3->hs.kea_def->exchKeyType; + certIndex = ss->ssl3.hs.kea_def->exchKeyType; } sc = ss->serverCerts + certIndex; certChain = sc->serverCertChain; ss->sec.authKeyBits = sc->serverKeyBits; - ss->sec.authAlgorithm = ss->ssl3->hs.kea_def->signKeyType; + ss->sec.authAlgorithm = ss->ssl3.hs.kea_def->signKeyType; ss->sec.localCert = CERT_DupCertificate(sc->serverCert); } else { - certChain = ss->ssl3->clientCertChain; - ss->sec.localCert = CERT_DupCertificate(ss->ssl3->clientCertificate); + certChain = ss->ssl3.clientCertChain; + ss->sec.localCert = CERT_DupCertificate(ss->ssl3.clientCertificate); } #ifdef NISCC_TEST @@ -7334,17 +6384,17 @@ ssl3_SendCertificate(sslSocket *ss) * from the cert database after they've been validated. */ static void -ssl3_CleanupPeerCerts(ssl3State *ssl3) +ssl3_CleanupPeerCerts(sslSocket *ss) { - PRArenaPool * arena = ssl3->peerCertArena; - ssl3CertNode *certs = (ssl3CertNode *)ssl3->peerCertChain; + PRArenaPool * arena = ss->ssl3.peerCertArena; + ssl3CertNode *certs = (ssl3CertNode *)ss->ssl3.peerCertChain; for (; certs; certs = certs->next) { CERT_DestroyCertificate(certs->cert); } if (arena) PORT_FreeArena(arena, PR_FALSE); - ssl3->peerCertArena = NULL; - ssl3->peerCertChain = NULL; + ss->ssl3.peerCertArena = NULL; + ss->ssl3.peerCertChain = NULL; } /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete @@ -7357,7 +6407,6 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) ssl3CertNode * c; ssl3CertNode * certs = NULL; PRArenaPool * arena = NULL; - ssl3State * ssl3 = ss->ssl3; CERTCertificate *cert; PRInt32 remaining = 0; PRInt32 size; @@ -7371,11 +6420,11 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) SSL_TRC(3, ("%d: SSL3[%d]: handle certificate handshake", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); - if ((ssl3->hs.ws != wait_server_cert) && - (ssl3->hs.ws != wait_client_cert)) { + if ((ss->ssl3.hs.ws != wait_server_cert) && + (ss->ssl3.hs.ws != wait_client_cert)) { desc = unexpected_message; errCode = SSL_ERROR_RX_UNEXPECTED_CERTIFICATE; goto alert_loser; @@ -7390,8 +6439,8 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) ss->sec.peerCert = NULL; } - ssl3_CleanupPeerCerts(ssl3); - isTLS = (PRBool)(ssl3->prSpec->version > SSL_LIBRARY_VERSION_3_0); + ssl3_CleanupPeerCerts(ss); + isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0); /* It is reported that some TLS client sends a Certificate message ** with a zero-length message body. We'll treat that case like a @@ -7418,7 +6467,7 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) goto cert_block; } - ssl3->peerCertArena = arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + ss->ssl3.peerCertArena = arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if ( arena == NULL ) { goto loser; /* don't send alerts on memory errors */ } @@ -7493,18 +6542,8 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) SECKEY_UpdateCertPQG(ss->sec.peerCert); /* - * We're making a fortezza connection, and the card hasn't unloaded it's - * certs, try to unload those certs now. + * Ask caller-supplied callback function to validate cert chain. */ - if (!trusted) { - CERTCertificate *ccert; - - ccert = PK11_FindBestKEAMatch(ss->sec.peerCert, ss->pkcs11PinArg); - if (ccert) - CERT_DestroyCertificate(ccert); - } - - rv = (SECStatus)(*ss->authCertificate)(ss->authCertificateArg, ss->fd, PR_TRUE, isServer); if (rv) { @@ -7518,7 +6557,7 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) /* someone will handle this connection asynchronously*/ SSL_DBG(("%d: SSL3[%d]: go to async cert handler", SSL_GETPID(), ss->fd)); - ssl3->peerCertChain = certs; + ss->ssl3.peerCertChain = certs; certs = NULL; ssl_SetAlwaysBlock(ss); goto cert_block; @@ -7533,14 +6572,14 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) cert = ss->sec.peerCert; if (!isServer && ssl3_global_policy_some_restricted && - ssl3->policy == SSL_ALLOWED && + ss->ssl3.policy == SSL_ALLOWED && anyRestrictedEnabled(ss) && SECSuccess == CERT_VerifyCertNow(cert->dbhandle, cert, PR_FALSE, /* checkSig */ certUsageSSLServerWithStepUp, /*XXX*/ ss->authCertificateArg) ) { - ssl3->policy = SSL_RESTRICTED; - ssl3->hs.rehandshake = PR_TRUE; + ss->ssl3.policy = SSL_RESTRICTED; + ss->ssl3.hs.rehandshake = PR_TRUE; } ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert); @@ -7551,8 +6590,8 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) ** it will get fixed when we handle the server key exchange message. */ SECKEYPublicKey * pubKey = CERT_ExtractPublicKey(cert); - ss->sec.authAlgorithm = ssl3->hs.kea_def->signKeyType; - ss->sec.keaType = ssl3->hs.kea_def->exchKeyType; + ss->sec.authAlgorithm = ss->ssl3.hs.kea_def->signKeyType; + ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType; if (pubKey) { ss->sec.keaKeyBits = ss->sec.authKeyBits = SECKEY_PublicKeyStrengthInBits(pubKey); @@ -7565,7 +6604,7 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) * cert->signatureWrap.signature.len contains the * length of the encoded signature in bits. */ - if (ss->ssl3->hs.kea_def->kea == kea_ecdh_ecdsa) { + if (ss->ssl3.hs.kea_def->kea == kea_ecdh_ecdsa) { ss->sec.authKeyBits = cert->signatureWrap.signature.data[3]*8; if (cert->signatureWrap.signature.data[4] == 0x00) @@ -7574,7 +6613,7 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) * XXX: if cert is not signed by ecdsa we should * destroy pubKey and goto bad_cert */ - } else if (ss->ssl3->hs.kea_def->kea == kea_ecdh_rsa) { + } else if (ss->ssl3.hs.kea_def->kea == kea_ecdh_rsa) { ss->sec.authKeyBits = cert->signatureWrap.signature.len; /* * XXX: if cert is not signed by rsa we should @@ -7588,22 +6627,21 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } } - ssl3->peerCertChain = certs; certs = NULL; arena = NULL; + ss->ssl3.peerCertChain = certs; certs = NULL; arena = NULL; cert_block: if (ss->sec.isServer) { - ssl3->hs.ws = wait_client_key; + ss->ssl3.hs.ws = wait_client_key; } else { - ssl3->hs.ws = wait_cert_request; /* disallow server_key_exchange */ - if (ssl3->hs.kea_def->is_limited || + ss->ssl3.hs.ws = wait_cert_request; /* disallow server_key_exchange */ + if (ss->ssl3.hs.kea_def->is_limited || /* XXX OR server cert is signing only. */ - ssl3->hs.kea_def->kea == kea_fortezza || #ifdef NSS_ENABLE_ECC - ssl3->hs.kea_def->kea == kea_ecdhe_ecdsa || - ssl3->hs.kea_def->kea == kea_ecdhe_rsa || + ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa || + ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa || #endif /* NSS_ENABLE_ECC */ - ssl3->hs.kea_def->exchKeyType == kt_dh) { - ssl3->hs.ws = wait_server_key; /* allow server_key_exchange */ + ss->ssl3.hs.kea_def->exchKeyType == kt_dh) { + ss->ssl3.hs.ws = wait_server_key; /* allow server_key_exchange */ } } @@ -7660,8 +6698,8 @@ alert_loser: (void)SSL3_SendAlert(ss, alert_fatal, desc); loser: - ssl3->peerCertChain = certs; certs = NULL; arena = NULL; - ssl3_CleanupPeerCerts(ssl3); + ss->ssl3.peerCertChain = certs; certs = NULL; arena = NULL; + ssl3_CleanupPeerCerts(ss); if (ss->sec.peerCert != NULL) { CERT_DestroyCertificate(ss->sec.peerCert); @@ -7687,14 +6725,13 @@ int ssl3_RestartHandshakeAfterServerCert(sslSocket *ss) { CERTCertificate * cert; - ssl3State * ssl3 = ss->ssl3; int rv = SECSuccess; if (MSB(ss->version) != MSB(SSL_LIBRARY_VERSION_3_0)) { SET_ERROR_CODE return SECFailure; } - if (!ss->ssl3) { + if (!ss->ssl3.initialized) { SET_ERROR_CODE return SECFailure; } @@ -7704,14 +6741,14 @@ ssl3_RestartHandshakeAfterServerCert(sslSocket *ss) /* Permit step up if user decided to accept the cert */ if (!ss->sec.isServer && ssl3_global_policy_some_restricted && - ssl3->policy == SSL_ALLOWED && + ss->ssl3.policy == SSL_ALLOWED && anyRestrictedEnabled(ss) && (SECSuccess == CERT_VerifyCertNow(cert->dbhandle, cert, PR_FALSE, /* checksig */ certUsageSSLServerWithStepUp, /*XXX*/ ss->authCertificateArg) )) { - ssl3->policy = SSL_RESTRICTED; - ssl3->hs.rehandshake = PR_TRUE; + ss->ssl3.policy = SSL_RESTRICTED; + ss->ssl3.hs.rehandshake = PR_TRUE; } if (ss->handshake != NULL) { @@ -7719,7 +6756,7 @@ ssl3_RestartHandshakeAfterServerCert(sslSocket *ss) ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert); ssl_GetRecvBufLock(ss); - if (ssl3->hs.msgState.buf != NULL) { + if (ss->ssl3.hs.msgState.buf != NULL) { rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf); } ssl_ReleaseRecvBufLock(ss); @@ -7734,29 +6771,43 @@ ssl3_ComputeTLSFinished(ssl3CipherSpec *spec, const SSL3Finished * hashes, TLSFinished * tlsFinished) { - PK11Context *prf_context; const char * label; unsigned int len; SECStatus rv; - SECItem param = {siBuffer, NULL, 0}; label = isServer ? "server finished" : "client finished"; len = 15; - prf_context = - PK11_CreateContextBySymKey(CKM_TLS_PRF_GENERAL, CKA_SIGN, - spec->master_secret, ¶m); - if (!prf_context) - return SECFailure; + if (spec->master_secret && !spec->bypassCiphers) { + SECItem param = {siBuffer, NULL, 0}; + PK11Context *prf_context = + PK11_CreateContextBySymKey(CKM_TLS_PRF_GENERAL, CKA_SIGN, + spec->master_secret, ¶m); + if (!prf_context) + return SECFailure; - rv = PK11_DigestBegin(prf_context); - rv |= PK11_DigestOp(prf_context, (const unsigned char *) label, len); - rv |= PK11_DigestOp(prf_context, hashes->md5, sizeof *hashes); - rv |= PK11_DigestFinal(prf_context, tlsFinished->verify_data, - &len, sizeof *tlsFinished); - PORT_Assert(rv != SECSuccess || len == sizeof *tlsFinished); + rv = PK11_DigestBegin(prf_context); + rv |= PK11_DigestOp(prf_context, (const unsigned char *) label, len); + rv |= PK11_DigestOp(prf_context, hashes->md5, sizeof *hashes); + rv |= PK11_DigestFinal(prf_context, tlsFinished->verify_data, + &len, sizeof tlsFinished->verify_data); + PORT_Assert(rv != SECSuccess || len == sizeof *tlsFinished); - PK11_DestroyContext(prf_context, PR_TRUE); + PK11_DestroyContext(prf_context, PR_TRUE); + } else { + /* bypass PKCS11 */ + SECItem inData = { siBuffer, }; + SECItem outData = { siBuffer, }; + PRBool isFIPS = PR_FALSE; + + inData.data = (unsigned char *)hashes->md5; + inData.len = sizeof hashes[0]; + outData.data = tlsFinished->verify_data; + outData.len = sizeof tlsFinished->verify_data; + rv = TLS_PRF(&spec->msItem, label, &inData, &outData, isFIPS); + PORT_Assert(rv != SECSuccess || \ + outData.len == sizeof tlsFinished->verify_data); + } return rv; } @@ -7777,11 +6828,11 @@ ssl3_SendFinished(sslSocket *ss, PRInt32 flags) SSL_TRC(3, ("%d: SSL3[%d]: send finished handshake", SSL_GETPID(), ss->fd)); - PORT_Assert( ssl_HaveXmitBufLock(ss)); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); ssl_GetSpecReadLock(ss); - cwSpec = ss->ssl3->cwSpec; + cwSpec = ss->ssl3.cwSpec; isTLS = (PRBool)(cwSpec->version > SSL_LIBRARY_VERSION_3_0); rv = ssl3_ComputeHandshakeHashes(ss, cwSpec, &hashes, sender); if (isTLS && rv == SECSuccess) { @@ -7817,7 +6868,88 @@ fail: return rv; } +/* wrap the master secret, and put it into the SID. + * Caller holds the Spec read lock. + */ +static SECStatus +ssl3_CacheWrappedMasterSecret(sslSocket *ss, SSL3KEAType effectiveExchKeyType) +{ + sslSessionID * sid = ss->sec.ci.sid; + PK11SymKey * wrappingKey = NULL; + PK11SlotInfo * symKeySlot; + void * pwArg = ss->pkcs11PinArg; + SECStatus rv = SECFailure; + PRBool isServer = ss->sec.isServer; + CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; + symKeySlot = PK11_GetSlotFromKey(ss->ssl3.crSpec->master_secret); + if (!isServer) { + int wrapKeyIndex; + int incarnation; + + /* these next few functions are mere accessors and don't fail. */ + sid->u.ssl3.masterWrapIndex = wrapKeyIndex = + PK11_GetCurrentWrapIndex(symKeySlot); + PORT_Assert(wrapKeyIndex == 0); /* array has only one entry! */ + + sid->u.ssl3.masterWrapSeries = incarnation = + PK11_GetSlotSeries(symKeySlot); + sid->u.ssl3.masterSlotID = PK11_GetSlotID(symKeySlot); + sid->u.ssl3.masterModuleID = PK11_GetModuleID(symKeySlot); + sid->u.ssl3.masterValid = PR_TRUE; + /* Get the default wrapping key, for wrapping the master secret before + * placing it in the SID cache entry. */ + wrappingKey = PK11_GetWrapKey(symKeySlot, wrapKeyIndex, + CKM_INVALID_MECHANISM, incarnation, + pwArg); + if (wrappingKey) { + mechanism = PK11_GetMechanism(wrappingKey); /* can't fail. */ + } else { + int keyLength; + /* if the wrappingKey doesn't exist, attempt to create it. + * Note: we intentionally ignore errors here. If we cannot + * generate a wrapping key, it is not fatal to this SSL connection, + * but we will not be able to restart this session. + */ + mechanism = PK11_GetBestWrapMechanism(symKeySlot); + keyLength = PK11_GetBestKeyLength(symKeySlot, mechanism); + /* Zero length means fixed key length algorithm, or error. + * It's ambiguous. + */ + wrappingKey = PK11_KeyGen(symKeySlot, mechanism, NULL, + keyLength, pwArg); + if (wrappingKey) { + PK11_SetWrapKey(symKeySlot, wrapKeyIndex, wrappingKey); + } + } + } else { + /* server socket using session cache. */ + mechanism = PK11_GetBestWrapMechanism(symKeySlot); + if (mechanism != CKM_INVALID_MECHANISM) { + wrappingKey = + getWrappingKey(ss, symKeySlot, effectiveExchKeyType, + mechanism, pwArg); + if (wrappingKey) { + mechanism = PK11_GetMechanism(wrappingKey); /* can't fail. */ + } + } + } + + sid->u.ssl3.masterWrapMech = mechanism; + PK11_FreeSlot(symKeySlot); + if (wrappingKey) { + SECItem wmsItem; + + wmsItem.data = sid->u.ssl3.keys.wrapped_master_secret; + wmsItem.len = sizeof sid->u.ssl3.keys.wrapped_master_secret; + rv = PK11_WrapSymKey(mechanism, NULL, wrappingKey, + ss->ssl3.crSpec->master_secret, &wmsItem); + /* rv is examined below. */ + sid->u.ssl3.keys.wrapped_master_secret_len = wmsItem.len; + PK11_FreeSymKey(wrappingKey); + } + return rv; +} /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete * ssl3 Finished message from the peer. @@ -7827,31 +6959,26 @@ static SECStatus ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length, const SSL3Hashes *hashes) { - ssl3State * ssl3 = ss->ssl3; sslSessionID * sid = ss->sec.ci.sid; - PK11SymKey * wrappingKey = NULL; - PK11SlotInfo * symKeySlot; - void * pwArg = ss->pkcs11PinArg; - SECStatus rv; + SECStatus rv = SECSuccess; PRBool isServer = ss->sec.isServer; PRBool isTLS; PRBool doStepUp; - CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; SSL3KEAType effectiveExchKeyType; - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); SSL_TRC(3, ("%d: SSL3[%d]: handle finished handshake", SSL_GETPID(), ss->fd)); - if (ssl3->hs.ws != wait_finished) { + if (ss->ssl3.hs.ws != wait_finished) { SSL3_SendAlert(ss, alert_fatal, unexpected_message); PORT_SetError(SSL_ERROR_RX_UNEXPECTED_FINISHED); return SECFailure; } - isTLS = (PRBool)(ssl3->crSpec->version > SSL_LIBRARY_VERSION_3_0); + isTLS = (PRBool)(ss->ssl3.crSpec->version > SSL_LIBRARY_VERSION_3_0); if (isTLS) { TLSFinished tlsFinished; @@ -7860,7 +6987,7 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length, PORT_SetError(SSL_ERROR_RX_MALFORMED_FINISHED); return SECFailure; } - rv = ssl3_ComputeTLSFinished(ssl3->crSpec, !isServer, + rv = ssl3_ComputeTLSFinished(ss->ssl3.crSpec, !isServer, hashes, &tlsFinished); if (rv != SECSuccess || 0 != PORT_Memcmp(&tlsFinished, b, length)) { @@ -7882,12 +7009,12 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length, } } - doStepUp = (PRBool)(!isServer && ssl3->hs.rehandshake); + doStepUp = (PRBool)(!isServer && ss->ssl3.hs.rehandshake); ssl_GetXmitBufLock(ss); /*************************************/ - if ((isServer && !ssl3->hs.isResuming) || - (!isServer && ssl3->hs.isResuming)) { + if ((isServer && !ss->ssl3.hs.isResuming) || + (!isServer && ss->ssl3.hs.isResuming)) { PRInt32 flags = 0; rv = ssl3_SendChangeCipherSpecs(ss); @@ -7913,7 +7040,7 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length, if (doStepUp) { ssl_FreeSID(sid); ss->sec.ci.sid = sid = NULL; - ssl3->hs.rehandshake = PR_FALSE; + ss->ssl3.hs.rehandshake = PR_FALSE; rv = ssl3_SendClientHello(ss); xmit_loser: ssl_ReleaseXmitBufLock(ss); @@ -7928,113 +7055,52 @@ xmit_loser: ss->gs.writeOffset = 0; ss->gs.readOffset = 0; - if (ssl3->hs.kea_def->kea == kea_ecdhe_rsa) { + if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) { effectiveExchKeyType = kt_rsa; } else { - effectiveExchKeyType = ssl3->hs.kea_def->exchKeyType; - } - - if (sid->cached == never_cached) { - - /* fill in the sid */ - sid->u.ssl3.cipherSuite = ssl3->hs.cipher_suite; - sid->u.ssl3.compression = ssl3->hs.compression; - sid->u.ssl3.policy = ssl3->policy; - sid->u.ssl3.exchKeyType = effectiveExchKeyType; - sid->version = ss->version; - sid->authAlgorithm = ss->sec.authAlgorithm; - sid->authKeyBits = ss->sec.authKeyBits; - sid->keaType = ss->sec.keaType; - sid->keaKeyBits = ss->sec.keaKeyBits; - sid->lastAccessTime = sid->creationTime = ssl_Time(); - sid->expirationTime = sid->creationTime + ssl3_sid_timeout; - sid->localCert = CERT_DupCertificate(ss->sec.localCert); - - ssl_GetSpecReadLock(ss); /*************************************/ - symKeySlot = PK11_GetSlotFromKey(ssl3->crSpec->master_secret); - if (!isServer) { - int wrapKeyIndex; - int incarnation; - - /* these next few functions are mere accessors and don't fail. */ - sid->u.ssl3.masterWrapIndex = wrapKeyIndex = - PK11_GetCurrentWrapIndex(symKeySlot); - PORT_Assert(wrapKeyIndex == 0); /* array has only one entry! */ - - sid->u.ssl3.masterWrapSeries = incarnation = - PK11_GetSlotSeries(symKeySlot); - sid->u.ssl3.masterSlotID = PK11_GetSlotID(symKeySlot); - sid->u.ssl3.masterModuleID = PK11_GetModuleID(symKeySlot); - sid->u.ssl3.masterValid = PR_TRUE; - - /* Get the default wrapping key, for wrapping the master secret before - * placing it in the SID cache entry. */ - wrappingKey = PK11_GetWrapKey(symKeySlot, wrapKeyIndex, - CKM_INVALID_MECHANISM, incarnation, - pwArg); - if (wrappingKey) { - mechanism = PK11_GetMechanism(wrappingKey); /* can't fail. */ + effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType; + } + + if (sid->cached == never_cached && !ss->opt.noCache && ss->sec.cache) { + /* fill in the sid */ + sid->u.ssl3.cipherSuite = ss->ssl3.hs.cipher_suite; + sid->u.ssl3.compression = ss->ssl3.hs.compression; + sid->u.ssl3.policy = ss->ssl3.policy; + sid->u.ssl3.exchKeyType = effectiveExchKeyType; + sid->version = ss->version; + sid->authAlgorithm = ss->sec.authAlgorithm; + sid->authKeyBits = ss->sec.authKeyBits; + sid->keaType = ss->sec.keaType; + sid->keaKeyBits = ss->sec.keaKeyBits; + sid->lastAccessTime = sid->creationTime = ssl_Time(); + sid->expirationTime = sid->creationTime + ssl3_sid_timeout; + sid->localCert = CERT_DupCertificate(ss->sec.localCert); + + ssl_GetSpecReadLock(ss); /*************************************/ + + /* Copy the master secret (wrapped or unwrapped) into the sid */ + if (ss->ssl3.crSpec->msItem.len && ss->ssl3.crSpec->msItem.data) { + sid->u.ssl3.keys.wrapped_master_secret_len = + ss->ssl3.crSpec->msItem.len; + memcpy(sid->u.ssl3.keys.wrapped_master_secret, + ss->ssl3.crSpec->msItem.data, ss->ssl3.crSpec->msItem.len); + sid->u.ssl3.masterValid = PR_TRUE; + sid->u.ssl3.keys.msIsWrapped = PR_FALSE; + rv = SECSuccess; } else { - int keyLength; - /* if the wrappingKey doesn't exist, attempt to create it. - * Note: we intentionally ignore errors here. If we cannot - * generate a wrapping key, it is not fatal to this SSL connection, - * but we will not be able to restart this session. - */ - mechanism = PK11_GetBestWrapMechanism(symKeySlot); - keyLength = PK11_GetBestKeyLength(symKeySlot, mechanism); - /* Zero length means fixed key length algorithm, or error. - * It's ambiguous. - */ - wrappingKey = PK11_KeyGen(symKeySlot, mechanism, NULL, - keyLength, pwArg); - if (wrappingKey) { - PK11_SetWrapKey(symKeySlot, wrapKeyIndex, wrappingKey); - } - } - } else if (!ss->noCache) { - /* server socket using session cache. */ - mechanism = PK11_GetBestWrapMechanism(symKeySlot); - if (mechanism != CKM_INVALID_MECHANISM) { - wrappingKey = - getWrappingKey(ss, symKeySlot, effectiveExchKeyType, - mechanism, pwArg); - if (wrappingKey) { - mechanism = PK11_GetMechanism(wrappingKey); /* can't fail. */ - } + rv = ssl3_CacheWrappedMasterSecret(ss, effectiveExchKeyType); + sid->u.ssl3.keys.msIsWrapped = PR_TRUE; } - } - - sid->u.ssl3.masterWrapMech = mechanism; - PK11_FreeSlot(symKeySlot); - - rv = SECFailure; - if (wrappingKey) { - SECItem msItem; + ssl_ReleaseSpecReadLock(ss); /*************************************/ - msItem.data = sid->u.ssl3.keys.wrapped_master_secret; - msItem.len = sizeof sid->u.ssl3.keys.wrapped_master_secret; - rv = PK11_WrapSymKey(mechanism, NULL, wrappingKey, - ssl3->crSpec->master_secret, &msItem); - /* rv is examined below. */ - sid->u.ssl3.keys.wrapped_master_secret_len = msItem.len; - PK11_FreeSymKey(wrappingKey); - } - ssl_ReleaseSpecReadLock(ss); /*************************************/ - - /* If the wrap failed, we don't cache the sid. - * The connection continues normally however. - */ - if (!ss->noCache && rv == SECSuccess) { - if (ss->sec.cache) { + /* If the wrap failed, we don't cache the sid. + * The connection continues normally however. + */ + if (rv == SECSuccess) { (*ss->sec.cache)(sid); - } else { - PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED); - return SECFailure; } } - } - ss->ssl3->hs.ws = idle_handshake; + ss->ssl3.hs.ws = idle_handshake; /* Do the handshake callback for sslv3 here. */ if (ss->handshakeCallback != NULL) { @@ -8052,12 +7118,12 @@ static SECStatus ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length) { SECStatus rv = SECSuccess; - SSL3HandshakeType type = ss->ssl3->hs.msg_type; + SSL3HandshakeType type = ss->ssl3.hs.msg_type; SSL3Hashes hashes; /* computed hashes are put here. */ PRUint8 hdr[4]; - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); /* * We have to compute the hashes before we update them with the * current message. @@ -8065,11 +7131,11 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length) ssl_GetSpecReadLock(ss); /************************************/ if((type == finished) || (type == certificate_verify)) { SSL3Sender sender = (SSL3Sender)0; - ssl3CipherSpec *rSpec = ss->ssl3->prSpec; + ssl3CipherSpec *rSpec = ss->ssl3.prSpec; if (type == finished) { sender = ss->sec.isServer ? sender_client : sender_server; - rSpec = ss->ssl3->crSpec; + rSpec = ss->ssl3.crSpec; } rv = ssl3_ComputeHandshakeHashes(ss, rSpec, &hashes, sender); } @@ -8078,34 +7144,39 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length) return rv; /* error code was set by ssl3_ComputeHandshakeHashes*/ } SSL_TRC(30,("%d: SSL3[%d]: handle handshake message: %s", SSL_GETPID(), - ss->fd, ssl3_DecodeHandshakeType(ss->ssl3->hs.msg_type))); + ss->fd, ssl3_DecodeHandshakeType(ss->ssl3.hs.msg_type))); PRINT_BUF(60, (ss, "MD5 handshake hash:", - (unsigned char*)ss->ssl3->hs.md5, MD5_LENGTH)); + (unsigned char*)ss->ssl3.hs.md5_cx, MD5_LENGTH)); PRINT_BUF(95, (ss, "SHA handshake hash:", - (unsigned char*)ss->ssl3->hs.sha, SHA1_LENGTH)); + (unsigned char*)ss->ssl3.hs.sha_cx, SHA1_LENGTH)); - hdr[0] = (PRUint8)ss->ssl3->hs.msg_type; + hdr[0] = (PRUint8)ss->ssl3.hs.msg_type; hdr[1] = (PRUint8)(length >> 16); hdr[2] = (PRUint8)(length >> 8); hdr[3] = (PRUint8)(length ); /* Start new handshake hashes when we start a new handshake */ - if (ss->ssl3->hs.msg_type == client_hello) { + if (ss->ssl3.hs.msg_type == client_hello) { SSL_TRC(30,("%d: SSL3[%d]: reset handshake hashes", SSL_GETPID(), ss->fd )); - rv = PK11_DigestBegin(ss->ssl3->hs.md5); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); - return rv; - } - rv = PK11_DigestBegin(ss->ssl3->hs.sha); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); - return rv; + if (ss->opt.bypassPKCS11) { + MD5_Begin((MD5Context *)ss->ssl3.hs.md5_cx); + SHA1_Begin((SHA1Context *)ss->ssl3.hs.sha_cx); + } else { + rv = PK11_DigestBegin(ss->ssl3.hs.md5); + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); + return rv; + } + rv = PK11_DigestBegin(ss->ssl3.hs.sha); + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); + return rv; + } } } /* We should not include hello_request messages in the handshake hashes */ - if (ss->ssl3->hs.msg_type != hello_request) { + if (ss->ssl3.hs.msg_type != hello_request) { rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char*) hdr, 4); if (rv != SECSuccess) return rv; /* err code already set. */ rv = ssl3_UpdateHandshakeHashes(ss, b, length); @@ -8113,7 +7184,7 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } PORT_SetError(0); /* each message starts with no error. */ - switch (ss->ssl3->hs.msg_type) { + switch (ss->ssl3.hs.msg_type) { case hello_request: if (length != 0) { (void)ssl3_DecodeError(ss); @@ -8217,30 +7288,29 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) * Each message is made contiguous before being passed to the actual * message parser. */ - ssl3State *ssl3 = ss->ssl3; - sslBuffer *buf = &ssl3->hs.msgState; /* do not lose the original buffer pointer */ + sslBuffer *buf = &ss->ssl3.hs.msgState; /* do not lose the original buffer pointer */ SECStatus rv; - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); if (buf->buf == NULL) { *buf = *origBuf; } while (buf->len > 0) { - if (ssl3->hs.header_bytes < 4) { + if (ss->ssl3.hs.header_bytes < 4) { uint8 t; t = *(buf->buf++); buf->len--; - if (ssl3->hs.header_bytes++ == 0) - ssl3->hs.msg_type = (SSL3HandshakeType)t; + if (ss->ssl3.hs.header_bytes++ == 0) + ss->ssl3.hs.msg_type = (SSL3HandshakeType)t; else - ssl3->hs.msg_len = (ssl3->hs.msg_len << 8) + t; - if (ssl3->hs.header_bytes < 4) + ss->ssl3.hs.msg_len = (ss->ssl3.hs.msg_len << 8) + t; + if (ss->ssl3.hs.header_bytes < 4) continue; #define MAX_HANDSHAKE_MSG_LEN 0x1ffff /* 128k - 1 */ - if (ssl3->hs.msg_len > MAX_HANDSHAKE_MSG_LEN) { + if (ss->ssl3.hs.msg_len > MAX_HANDSHAKE_MSG_LEN) { (void)ssl3_DecodeError(ss); PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG); return SECFailure; @@ -8250,7 +7320,7 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) /* If msg_len is zero, be sure we fall through, ** even if buf->len is zero. */ - if (ssl3->hs.msg_len > 0) + if (ss->ssl3.hs.msg_len > 0) continue; } @@ -8259,9 +7329,9 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) * data available for this message. If it can be done right out * of the original buffer, then use it from there. */ - if (ssl3->hs.msg_body.len == 0 && buf->len >= ssl3->hs.msg_len) { + if (ss->ssl3.hs.msg_body.len == 0 && buf->len >= ss->ssl3.hs.msg_len) { /* handle it from input buffer */ - rv = ssl3_HandleHandshakeMessage(ss, buf->buf, ssl3->hs.msg_len); + rv = ssl3_HandleHandshakeMessage(ss, buf->buf, ss->ssl3.hs.msg_len); if (rv == SECFailure) { /* This test wants to fall through on either * SECSuccess or SECWouldBlock. @@ -8269,10 +7339,10 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) */ return rv; } - buf->buf += ssl3->hs.msg_len; - buf->len -= ssl3->hs.msg_len; - ssl3->hs.msg_len = 0; - ssl3->hs.header_bytes = 0; + buf->buf += ss->ssl3.hs.msg_len; + buf->len -= ss->ssl3.hs.msg_len; + ss->ssl3.hs.msg_len = 0; + ss->ssl3.hs.header_bytes = 0; if (rv != SECSuccess) { /* return if SECWouldBlock. */ return rv; } @@ -8280,28 +7350,28 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) /* must be copied to msg_body and dealt with from there */ unsigned int bytes; - PORT_Assert(ssl3->hs.msg_body.len <= ssl3->hs.msg_len); - bytes = PR_MIN(buf->len, ssl3->hs.msg_len - ssl3->hs.msg_body.len); + PORT_Assert(ss->ssl3.hs.msg_body.len <= ss->ssl3.hs.msg_len); + bytes = PR_MIN(buf->len, ss->ssl3.hs.msg_len - ss->ssl3.hs.msg_body.len); /* Grow the buffer if needed */ - rv = sslBuffer_Grow(&ssl3->hs.msg_body, ssl3->hs.msg_len); + rv = sslBuffer_Grow(&ss->ssl3.hs.msg_body, ss->ssl3.hs.msg_len); if (rv != SECSuccess) { /* sslBuffer_Grow has set a memory error code. */ return SECFailure; } - PORT_Memcpy(ssl3->hs.msg_body.buf + ssl3->hs.msg_body.len, + PORT_Memcpy(ss->ssl3.hs.msg_body.buf + ss->ssl3.hs.msg_body.len, buf->buf, bytes); - ssl3->hs.msg_body.len += bytes; + ss->ssl3.hs.msg_body.len += bytes; buf->buf += bytes; buf->len -= bytes; - PORT_Assert(ssl3->hs.msg_body.len <= ssl3->hs.msg_len); + PORT_Assert(ss->ssl3.hs.msg_body.len <= ss->ssl3.hs.msg_len); /* if we have a whole message, do it */ - if (ssl3->hs.msg_body.len == ssl3->hs.msg_len) { + if (ss->ssl3.hs.msg_body.len == ss->ssl3.hs.msg_len) { rv = ssl3_HandleHandshakeMessage( - ss, ssl3->hs.msg_body.buf, ssl3->hs.msg_len); + ss, ss->ssl3.hs.msg_body.buf, ss->ssl3.hs.msg_len); /* * XXX This appears to be wrong. This error handling * should clean up after a SECWouldBlock return, like the @@ -8311,9 +7381,9 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) /* ssl3_HandleHandshakeMessage MUST set error code. */ return rv; } - ssl3->hs.msg_body.len = 0; - ssl3->hs.msg_len = 0; - ssl3->hs.header_bytes = 0; + ss->ssl3.hs.msg_body.len = 0; + ss->ssl3.hs.msg_len = 0; + ss->ssl3.hs.header_bytes = 0; } else { PORT_Assert(buf->len == 0); break; @@ -8353,7 +7423,6 @@ SECStatus ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) { const ssl3BulkCipherDef *cipher_def; - ssl3State * ssl3 = ss->ssl3; ssl3CipherSpec * crSpec; SECStatus rv; unsigned int hashBytes = MAX_MAC_LENGTH + 1; @@ -8363,9 +7432,9 @@ const ssl3BulkCipherDef *cipher_def; SSL3ContentType rType; SSL3Opaque hash[MAX_MAC_LENGTH]; - PORT_Assert( ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); - if (ssl3 == NULL) { + if (!ss->ssl3.initialized) { ssl_GetSSL3HandshakeLock(ss); rv = ssl3_InitState(ss); ssl_ReleaseSSL3HandshakeLock(ss); @@ -8374,8 +7443,6 @@ const ssl3BulkCipherDef *cipher_def; } } - ssl3 = ss->ssl3; - /* check for Token Presence */ if (!ssl3_ClientAuthTokenPresent(ss->sec.ci.sid)) { PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL); @@ -8409,7 +7476,7 @@ const ssl3BulkCipherDef *cipher_def; ssl_GetSpecReadLock(ss); /******************************************/ - crSpec = ssl3->crSpec; + crSpec = ss->ssl3.crSpec; cipher_def = crSpec->cipher_def; isTLS = (PRBool)(crSpec->version > SSL_LIBRARY_VERSION_3_0); @@ -8457,9 +7524,7 @@ const ssl3BulkCipherDef *cipher_def; /* compute the MAC */ rType = cText->type; - rv = ssl3_ComputeRecordMAC( - crSpec, (ss->sec.isServer) ? crSpec->client.write_mac_context - : crSpec->server.write_mac_context, + rv = ssl3_ComputeRecordMAC( crSpec, (PRBool)(!ss->sec.isServer), rType, cText->version, crSpec->read_seq_num, databuf->buf, databuf->len, hash, &hashBytes); if (rv != SECSuccess) { @@ -8566,6 +7631,10 @@ ssl3_InitCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) spec->destroy = NULL; spec->mac_size = 0; spec->master_secret = NULL; + spec->bypassCiphers = PR_FALSE; + + spec->msItem.data = NULL; + spec->msItem.len = 0; spec->client.write_key = NULL; spec->client.write_mac_key = NULL; @@ -8581,7 +7650,7 @@ ssl3_InitCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) spec->read_seq_num.high = 0; spec->read_seq_num.low = 0; - spec->version = ss->enableTLS + spec->version = ss->opt.enableTLS ? SSL_LIBRARY_VERSION_3_1_TLS : SSL_LIBRARY_VERSION_3_0; } @@ -8601,33 +7670,24 @@ ssl3_InitCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) static SECStatus ssl3_InitState(sslSocket *ss) { - ssl3State * ssl3 = NULL; PK11Context *md5 = NULL; PK11Context *sha = NULL; SECStatus rv; + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss)); - - /* reinitialization for renegotiated sessions XXX */ - if (ss->ssl3 != NULL) - return SECSuccess; + if (ss->ssl3.initialized) + return SECSuccess; /* Function should be idempotent */ - ssl3 = PORT_ZNew(ssl3State); /* zero on purpose */ - if (ssl3 == NULL) - return SECFailure; /* PORT_ZAlloc has set memory error code. */ - - /* note that entire HandshakeState is zero, including the buffer */ - ssl3->policy = SSL_ALLOWED; + ss->ssl3.policy = SSL_ALLOWED; ssl_GetSpecWriteLock(ss); - ssl3->crSpec = ssl3->cwSpec = &ssl3->specs[0]; - ssl3->prSpec = ssl3->pwSpec = &ssl3->specs[1]; - ssl3->hs.rehandshake = PR_FALSE; - ssl3_InitCipherSpec(ss, ssl3->crSpec); - ssl3_InitCipherSpec(ss, ssl3->prSpec); - ssl3->fortezza.tek = NULL; - - ssl3->hs.ws = (ss->sec.isServer) ? wait_client_hello : wait_server_hello; + ss->ssl3.crSpec = ss->ssl3.cwSpec = &ss->ssl3.specs[0]; + ss->ssl3.prSpec = ss->ssl3.pwSpec = &ss->ssl3.specs[1]; + ss->ssl3.hs.rehandshake = PR_FALSE; + ssl3_InitCipherSpec(ss, ss->ssl3.crSpec); + ssl3_InitCipherSpec(ss, ss->ssl3.prSpec); + + ss->ssl3.hs.ws = (ss->sec.isServer) ? wait_client_hello : wait_server_hello; ssl_ReleaseSpecWriteLock(ss); /* @@ -8636,37 +7696,40 @@ ssl3_InitState(sslSocket *ss) * that the master secret will wind up in ... */ SSL_TRC(30,("%d: SSL3[%d]: start handshake hashes", SSL_GETPID(), ss->fd)); - ssl3->hs.md5 = md5 = PK11_CreateDigestContext(SEC_OID_MD5); - if (md5 == NULL) { - ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); - goto loser; - } - rv = PK11_DigestBegin(ssl3->hs.md5); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); - goto loser; - } + if (ss->opt.bypassPKCS11) { + MD5_Begin((MD5Context *)ss->ssl3.hs.md5_cx); + SHA1_Begin((SHA1Context *)ss->ssl3.hs.sha_cx); + } else { + ss->ssl3.hs.md5 = md5 = PK11_CreateDigestContext(SEC_OID_MD5); + if (md5 == NULL) { + ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); + goto loser; + } + rv = PK11_DigestBegin(ss->ssl3.hs.md5); + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); + goto loser; + } - sha = ssl3->hs.sha = PK11_CreateDigestContext(SEC_OID_SHA1); - if (sha == NULL) { - ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); - goto loser; - } - rv = PK11_DigestBegin(ssl3->hs.sha); - if (rv != SECSuccess) { - ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); - goto loser; + sha = ss->ssl3.hs.sha = PK11_CreateDigestContext(SEC_OID_SHA1); + if (sha == NULL) { + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); + goto loser; + } + rv = PK11_DigestBegin(ss->ssl3.hs.sha); + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); + goto loser; + } } - /* Don't hide this from the rest of the world any more. */ - ss->ssl3 = ssl3; + ss->ssl3.initialized = PR_TRUE; return SECSuccess; loser: if (md5 != NULL) PK11_DestroyContext(md5, PR_TRUE); if (sha != NULL) PK11_DestroyContext(sha, PR_TRUE); - if (ssl3 != NULL) PORT_Free(ssl3); return SECFailure; } @@ -8679,7 +7742,8 @@ ssl3_NewKeyPair( SECKEYPrivateKey * privKey, SECKEYPublicKey * pubKey) { ssl3KeyPair * pair; - if (!privKey || !pubKey) { + if (!privKey && !pubKey) { + /* one or the other may be NULL, but not both. */ PORT_SetError(PR_INVALID_ARGUMENT_ERROR); return NULL; } @@ -8704,8 +7768,10 @@ ssl3_FreeKeyPair(ssl3KeyPair * keyPair) { PRInt32 newCount = PR_AtomicDecrement(&keyPair->refCount); if (!newCount) { - SECKEY_DestroyPrivateKey(keyPair->privKey); - SECKEY_DestroyPublicKey( keyPair->pubKey); + if (keyPair->privKey) + SECKEY_DestroyPrivateKey(keyPair->privKey); + if (keyPair->pubKey) + SECKEY_DestroyPublicKey( keyPair->pubKey); PORT_Free(keyPair); } } @@ -8728,7 +7794,7 @@ ssl3_CreateRSAStepDownKeys(sslSocket *ss) ss->stepDownKeyPair = NULL; #ifndef HACKED_EXPORT_SERVER /* Sigh, should have a get key strength call for private keys */ - if (PK11_GetPrivateModulusLen(ss->serverCerts[kt_rsa].serverKey) > + if (PK11_GetPrivateModulusLen(ss->serverCerts[kt_rsa].SERVERKEY) > EXPORT_RSA_KEY_LENGTH) { /* need to ask for the key size in bits */ privKey = SECKEY_CreateRSAPrivateKey(EXPORT_RSA_KEY_LENGTH * BPB, @@ -8743,40 +7809,6 @@ ssl3_CreateRSAStepDownKeys(sslSocket *ss) return rv; } -#ifdef NSS_ENABLE_ECC -/* - * Creates the ephemeral public and private ECDH keys used by - * server in ECDHE_RSA and ECDHE_ECDSA handshakes. - * XXX For now, the elliptic curve is hardcoded to NIST P-224. - * We need an API to specify the curve. This won't be a real - * issue until we further develop server-side support for ECC - * cipher suites. - */ -SECStatus -ssl3_CreateECDHEphemeralKeys(sslSocket *ss) -{ - SECStatus rv = SECSuccess; - SECKEYPrivateKey * privKey; - SECKEYPublicKey * pubKey; - SECKEYECParams ecParams = { siBuffer, NULL, 0 }; - - if (ss->ephemeralECDHKeyPair) - ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair); - ss->ephemeralECDHKeyPair = NULL; - - if (ecName2params(NULL, ec_secp224r1, &ecParams) == SECFailure) - return SECFailure; - privKey = SECKEY_CreateECPrivateKey(&ecParams, &pubKey, NULL); - if (!privKey || !pubKey || - !(ss->ephemeralECDHKeyPair = ssl3_NewKeyPair(privKey, pubKey))) { - ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL); - rv = SECFailure; - } - - PORT_Free(ecParams.data); - return rv; -} -#endif /* NSS_ENABLE_ECC */ /* record the export policy for this cipher suite */ SECStatus @@ -8902,7 +7934,7 @@ ssl3_ConstructV2CipherSpecsHack(sslSocket *ss, unsigned char *cs, int *size) PORT_SetError(PR_INVALID_ARGUMENT_ERROR); return SECFailure; } - if (!ss->enableSSL3 && !ss->enableTLS) { + if (!ss->opt.enableSSL3 && !ss->opt.enableTLS) { *size = 0; return SECSuccess; } @@ -8941,11 +7973,12 @@ ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache) sslSessionID * sid = ss->sec.ci.sid; SECStatus rv; - PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); if (!ss->firstHsDone || ((ss->version >= SSL_LIBRARY_VERSION_3_0) && - ss->ssl3 && (ss->ssl3->hs.ws != idle_handshake))) { + ss->ssl3.initialized && + (ss->ssl3.hs.ws != idle_handshake))) { PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED); return SECFailure; } @@ -8967,44 +8000,43 @@ ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache) /* Called from ssl_FreeSocket() in sslsock.c */ void -ssl3_DestroySSL3Info(ssl3State *ssl3) +ssl3_DestroySSL3Info(sslSocket *ss) { - if (ssl3 == NULL) - return; /* success the easy way. */ - if (ssl3->clientCertificate != NULL) - CERT_DestroyCertificate(ssl3->clientCertificate); + if (ss->ssl3.clientCertificate != NULL) + CERT_DestroyCertificate(ss->ssl3.clientCertificate); - if (ssl3->clientPrivateKey != NULL) - SECKEY_DestroyPrivateKey(ssl3->clientPrivateKey); + if (ss->ssl3.clientPrivateKey != NULL) + SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey); - if (ssl3->peerCertArena != NULL) - ssl3_CleanupPeerCerts(ssl3); + if (ss->ssl3.peerCertArena != NULL) + ssl3_CleanupPeerCerts(ss); - if (ssl3->clientCertChain != NULL) { - CERT_DestroyCertificateList(ssl3->clientCertChain); - ssl3->clientCertChain = NULL; + if (ss->ssl3.clientCertChain != NULL) { + CERT_DestroyCertificateList(ss->ssl3.clientCertChain); + ss->ssl3.clientCertChain = NULL; } /* clean up handshake */ - if (ssl3->hs.md5) { - PK11_DestroyContext(ssl3->hs.md5,PR_TRUE); + if (ss->opt.bypassPKCS11) { + SHA1_DestroyContext((SHA1Context *)ss->ssl3.hs.sha_cx, PR_FALSE); + MD5_DestroyContext((MD5Context *)ss->ssl3.hs.md5_cx, PR_FALSE); + } + if (ss->ssl3.hs.md5) { + PK11_DestroyContext(ss->ssl3.hs.md5,PR_TRUE); } - if (ssl3->hs.sha) { - PK11_DestroyContext(ssl3->hs.sha,PR_TRUE); + if (ss->ssl3.hs.sha) { + PK11_DestroyContext(ss->ssl3.hs.sha,PR_TRUE); } - if (ssl3->fortezza.tek != NULL) { - PK11_FreeSymKey(ssl3->fortezza.tek); - } /* free the SSL3Buffer (msg_body) */ - PORT_Free(ssl3->hs.msg_body.buf); + PORT_Free(ss->ssl3.hs.msg_body.buf); /* free up the CipherSpecs */ - ssl3_DestroyCipherSpec(&ssl3->specs[0]); - ssl3_DestroyCipherSpec(&ssl3->specs[1]); + ssl3_DestroyCipherSpec(&ss->ssl3.specs[0]); + ssl3_DestroyCipherSpec(&ss->ssl3.specs[1]); - PORT_Free(ssl3); + ss->ssl3.initialized = PR_FALSE; } /* End of ssl3con.c */ diff --git a/security/nss/lib/ssl/ssl3ecc.c b/security/nss/lib/ssl/ssl3ecc.c new file mode 100644 index 000000000..af7cdb30f --- /dev/null +++ b/security/nss/lib/ssl/ssl3ecc.c @@ -0,0 +1,673 @@ +/* + * SSL3 Protocol + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Dr Vipul Gupta <vipul.gupta@sun.com> and + * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* ECC code moved here from ssl3con.c */ +/* $Id$ */ + +#ifdef NSS_ENABLE_ECC + +#include "nssrenam.h" +#include "cert.h" +#include "ssl.h" +#include "cryptohi.h" /* for DSAU_ stuff */ +#include "keyhi.h" +#include "secder.h" +#include "secitem.h" + +#include "sslimpl.h" +#include "sslproto.h" +#include "sslerr.h" +#include "prtime.h" +#include "prinrval.h" +#include "prerror.h" +#include "pratom.h" +#include "prthread.h" + +#include "pk11func.h" +#include "secmod.h" +#include "nsslocks.h" +#include "ec.h" +#include "blapi.h" + +#include <stdio.h> + +/* + line 297: implicit function declaration: ssl3_InitPendingCipherSpec + line 305: implicit function declaration: ssl3_AppendHandshakeHeader + line 311: implicit function declaration: ssl3_AppendHandshakeVariable + line 356: implicit function declaration: ssl3_ConsumeHandshakeVariable +*/ + + +#ifndef PK11_SETATTRS +#define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \ + (x)->pValue=(v); (x)->ulValueLen = (l); +#endif + +/* Types and names of elliptic curves used in TLS */ +typedef enum { ec_type_explicitPrime = 1, + ec_type_explicitChar2Curve, + ec_type_named +} ECType; + +typedef enum { ec_noName = 0, + ec_sect163k1, ec_sect163r1, ec_sect163r2, + ec_sect193r1, ec_sect193r2, ec_sect233k1, + ec_sect233r1, ec_sect239k1, ec_sect283k1, + ec_sect283r1, ec_sect409k1, ec_sect409r1, + ec_sect571k1, ec_sect571r1, ec_secp160k1, + ec_secp160r1, ec_secp160r2, ec_secp192k1, + ec_secp192r1, ec_secp224k1, ec_secp224r1, + ec_secp256k1, ec_secp256r1, ec_secp384r1, + ec_secp521r1, + ec_pastLastName +} ECName; + +#define supportedCurve(x) (((x) > ec_noName) && ((x) < ec_pastLastName)) + +/* Table containing OID tags for elliptic curves named in the + * ECC-TLS IETF draft. + */ +static const SECOidTag ecName2OIDTag[] = { + 0, + SEC_OID_SECG_EC_SECT163K1, /* 1 */ + SEC_OID_SECG_EC_SECT163R1, /* 2 */ + SEC_OID_SECG_EC_SECT163R2, /* 3 */ + SEC_OID_SECG_EC_SECT193R1, /* 4 */ + SEC_OID_SECG_EC_SECT193R2, /* 5 */ + SEC_OID_SECG_EC_SECT233K1, /* 6 */ + SEC_OID_SECG_EC_SECT233R1, /* 7 */ + SEC_OID_SECG_EC_SECT239K1, /* 8 */ + SEC_OID_SECG_EC_SECT283K1, /* 9 */ + SEC_OID_SECG_EC_SECT283R1, /* 10 */ + SEC_OID_SECG_EC_SECT409K1, /* 11 */ + SEC_OID_SECG_EC_SECT409R1, /* 12 */ + SEC_OID_SECG_EC_SECT571K1, /* 13 */ + SEC_OID_SECG_EC_SECT571R1, /* 14 */ + SEC_OID_SECG_EC_SECP160K1, /* 15 */ + SEC_OID_SECG_EC_SECP160R1, /* 16 */ + SEC_OID_SECG_EC_SECP160R2, /* 17 */ + SEC_OID_SECG_EC_SECP192K1, /* 18 */ + SEC_OID_SECG_EC_SECP192R1, /* 19 */ + SEC_OID_SECG_EC_SECP224K1, /* 20 */ + SEC_OID_SECG_EC_SECP224R1, /* 21 */ + SEC_OID_SECG_EC_SECP256K1, /* 22 */ + SEC_OID_SECG_EC_SECP256R1, /* 23 */ + SEC_OID_SECG_EC_SECP384R1, /* 24 */ + SEC_OID_SECG_EC_SECP521R1, /* 25 */ +}; + +static SECStatus +ecName2params(PRArenaPool * arena, ECName curve, SECKEYECParams * params) +{ + SECOidData *oidData = NULL; + + if ((curve <= ec_noName) || (curve >= ec_pastLastName) || + ((oidData = SECOID_FindOIDByTag(ecName2OIDTag[curve])) == NULL)) { + PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); + return SECFailure; + } + + SECITEM_AllocItem(arena, params, (2 + oidData->oid.len)); + /* + * params->data needs to contain the ASN encoding of an object ID (OID) + * representing the named curve. The actual OID is in + * oidData->oid.data so we simply prepend 0x06 and OID length + */ + params->data[0] = SEC_ASN1_OBJECT_ID; + params->data[1] = oidData->oid.len; + memcpy(params->data + 2, oidData->oid.data, oidData->oid.len); + + return SECSuccess; +} + +static ECName +params2ecName(SECKEYECParams * params) +{ + SECItem oid = { siBuffer, NULL, 0}; + SECOidData *oidData = NULL; + ECName i; + + /* + * params->data needs to contain the ASN encoding of an object ID (OID) + * representing a named curve. Here, we strip away everything + * before the actual OID and use the OID to look up a named curve. + */ + if (params->data[0] != SEC_ASN1_OBJECT_ID) return ec_noName; + oid.len = params->len - 2; + oid.data = params->data + 2; + if ((oidData = SECOID_FindOID(&oid)) == NULL) return ec_noName; + for (i = ec_noName + 1; i < ec_pastLastName; i++) { + if (ecName2OIDTag[i] == oidData->offset) + return i; + } + + return ec_noName; +} + +/* Caller must set hiLevel error code. */ +static SECStatus +ssl3_ComputeECDHKeyHash(SECItem ec_params, SECItem server_ecpoint, + SSL3Random *client_rand, SSL3Random *server_rand, + SSL3Hashes *hashes, PRBool bypassPKCS11) +{ + PRUint8 * hashBuf; + PRUint8 * pBuf; + SECStatus rv = SECSuccess; + unsigned int bufLen; + /* + * XXX For now, we only support named curves (the appropriate + * checks are made before this method is called) so ec_params + * takes up only two bytes. ECPoint needs to fit in 256 bytes + * (because the spec says the length must fit in one byte) + */ + PRUint8 buf[2*SSL3_RANDOM_LENGTH + 2 + 1 + 256]; + + bufLen = 2*SSL3_RANDOM_LENGTH + ec_params.len + 1 + server_ecpoint.len; + if (bufLen <= sizeof buf) { + hashBuf = buf; + } else { + hashBuf = PORT_Alloc(bufLen); + if (!hashBuf) { + return SECFailure; + } + } + + memcpy(hashBuf, client_rand, SSL3_RANDOM_LENGTH); + pBuf = hashBuf + SSL3_RANDOM_LENGTH; + memcpy(pBuf, server_rand, SSL3_RANDOM_LENGTH); + pBuf += SSL3_RANDOM_LENGTH; + memcpy(pBuf, ec_params.data, ec_params.len); + pBuf += ec_params.len; + pBuf[0] = (PRUint8)(server_ecpoint.len); + pBuf += 1; + memcpy(pBuf, server_ecpoint.data, server_ecpoint.len); + pBuf += server_ecpoint.len; + PORT_Assert((unsigned int)(pBuf - hashBuf) == bufLen); + + rv = ssl3_ComputeCommonKeyHash(hashBuf, bufLen, hashes, bypassPKCS11); + + PRINT_BUF(95, (NULL, "ECDHkey hash: ", hashBuf, bufLen)); + PRINT_BUF(95, (NULL, "ECDHkey hash: MD5 result", hashes->md5, MD5_LENGTH)); + PRINT_BUF(95, (NULL, "ECDHkey hash: SHA1 result", hashes->sha, SHA1_LENGTH)); + +done: + if (hashBuf != buf && hashBuf != NULL) + PORT_Free(hashBuf); + return rv; +} + + +/* Called from ssl3_SendClientKeyExchange(). */ +SECStatus +ssl3_SendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) +{ + PK11SymKey * pms = NULL; + SECStatus rv = SECFailure; + PRBool isTLS; + CK_MECHANISM_TYPE target; + SECKEYPublicKey *pubKey = NULL; /* Ephemeral ECDH key */ + SECKEYPrivateKey *privKey = NULL; /* Ephemeral ECDH key */ + CK_EC_KDF_TYPE kdf; + + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); + + isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); + + /* Generate ephemeral EC keypair */ + privKey = SECKEY_CreateECPrivateKey(&svrPubKey->u.ec.DEREncodedParams, + &pubKey, NULL); + if (!privKey || !pubKey) { + ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL); + rv = SECFailure; + goto loser; + } + PRINT_BUF(50, (ss, "ECDH public value:", + pubKey->u.ec.publicValue.data, + pubKey->u.ec.publicValue.len)); + + if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH; + else target = CKM_SSL3_MASTER_KEY_DERIVE_DH; + + /* If field size is not more than 24 octets, then use SHA-1 hash of result; + * otherwise, use result (see section 4.8 of draft-ietf-tls-ecc-03.txt). + */ + if ((pubKey->u.ec.publicValue.len - 1) / 2 <= 24) { + kdf = CKD_SHA1_KDF; + } else { + kdf = CKD_NULL; + } + + /* Determine the PMS */ + pms = PK11_PubDeriveWithKDF(privKey, svrPubKey, PR_FALSE, NULL, NULL, + CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0, + kdf, NULL, NULL); + + if (pms == NULL) { + ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); + goto loser; + } + + SECKEY_DestroyPrivateKey(privKey); + privKey = NULL; + + rv = ssl3_InitPendingCipherSpec(ss, pms); + PK11_FreeSymKey(pms); pms = NULL; + + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); + goto loser; + } + + rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, + pubKey->u.ec.publicValue.len + 1); + if (rv != SECSuccess) { + goto loser; /* err set by ssl3_AppendHandshake* */ + } + + rv = ssl3_AppendHandshakeVariable(ss, + pubKey->u.ec.publicValue.data, + pubKey->u.ec.publicValue.len, 1); + SECKEY_DestroyPublicKey(pubKey); + pubKey = NULL; + + if (rv != SECSuccess) { + goto loser; /* err set by ssl3_AppendHandshake* */ + } + + rv = SECSuccess; + +loser: + if(pms) PK11_FreeSymKey(pms); + if(privKey) SECKEY_DestroyPrivateKey(privKey); + if(pubKey) SECKEY_DestroyPublicKey(pubKey); + return rv; +} + + +/* +** Called from ssl3_HandleClientKeyExchange() +*/ +SECStatus +ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b, + PRUint32 length, + SECKEYPublicKey *srvrPubKey, + SECKEYPrivateKey *srvrPrivKey) +{ + PK11SymKey * pms; + SECStatus rv; + SECKEYPublicKey clntPubKey; + CK_MECHANISM_TYPE target; + PRBool isTLS; + CK_EC_KDF_TYPE kdf; + + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); + + clntPubKey.keyType = ecKey; + clntPubKey.u.ec.DEREncodedParams.len = + srvrPubKey->u.ec.DEREncodedParams.len; + clntPubKey.u.ec.DEREncodedParams.data = + srvrPubKey->u.ec.DEREncodedParams.data; + + rv = ssl3_ConsumeHandshakeVariable(ss, &clntPubKey.u.ec.publicValue, + 1, &b, &length); + if (rv != SECSuccess) { + SEND_ALERT + return SECFailure; /* XXX Who sets the error code?? */ + } + + isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0); + + if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH; + else target = CKM_SSL3_MASTER_KEY_DERIVE_DH; + + /* If field size is not more than 24 octets, then use SHA-1 hash of result; + * otherwise, use result (see section 4.8 of draft-ietf-tls-ecc-03.txt). + */ + if (srvrPubKey->u.ec.size <= 24 * 8) { + kdf = CKD_SHA1_KDF; + } else { + kdf = CKD_NULL; + } + + /* Determine the PMS */ + pms = PK11_PubDeriveWithKDF(srvrPrivKey, &clntPubKey, PR_FALSE, NULL, NULL, + CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0, + kdf, NULL, NULL); + + if (pms == NULL) { + /* last gasp. */ + ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); + return SECFailure; + } + + rv = ssl3_InitPendingCipherSpec(ss, pms); + PK11_FreeSymKey(pms); + if (rv != SECSuccess) { + SEND_ALERT + return SECFailure; /* error code set by ssl3_InitPendingCipherSpec */ + } + return SECSuccess; +} + + +/* + * Creates the ephemeral public and private ECDH keys used by + * server in ECDHE_RSA and ECDHE_ECDSA handshakes. + * XXX For now, the elliptic curve is hardcoded to NIST P-224. + * We need an API to specify the curve. This won't be a real + * issue until we further develop server-side support for ECC + * cipher suites. + */ +SECStatus +ssl3_CreateECDHEphemeralKeys(sslSocket *ss) +{ + SECStatus rv = SECSuccess; + SECKEYPrivateKey * privKey; + SECKEYPublicKey * pubKey; + SECKEYECParams ecParams = { siBuffer, NULL, 0 }; + + if (ss->ephemeralECDHKeyPair) + ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair); + ss->ephemeralECDHKeyPair = NULL; + + if (ecName2params(NULL, ec_secp224r1, &ecParams) == SECFailure) + return SECFailure; + privKey = SECKEY_CreateECPrivateKey(&ecParams, &pubKey, NULL); + if (!privKey || !pubKey || + !(ss->ephemeralECDHKeyPair = ssl3_NewKeyPair(privKey, pubKey))) { + ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL); + rv = SECFailure; + } + + PORT_Free(ecParams.data); + return rv; +} + +SECStatus +ssl3_HandleECDHServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) +{ + PRArenaPool * arena = NULL; + SECKEYPublicKey *peerKey = NULL; + PRBool isTLS; + SECStatus rv; + int errCode = SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH; + SSL3AlertDescription desc = illegal_parameter; + SSL3Hashes hashes; + SECItem signature = {siBuffer, NULL, 0}; + + SECItem ec_params = {siBuffer, NULL, 0}; + SECItem ec_point = {siBuffer, NULL, 0}; + unsigned char paramBuf[2]; + + isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0); + + /* XXX This works only for named curves, revisit this when + * we support generic curves. + */ + ec_params.len = 2; + ec_params.data = paramBuf; + rv = ssl3_ConsumeHandshake(ss, ec_params.data, ec_params.len, + &b, &length); + if (rv != SECSuccess) { + goto loser; /* malformed. */ + } + + /* Fail if the curve is not a named curve */ + if ((ec_params.data[0] != ec_type_named) || + !supportedCurve(ec_params.data[1])) { + errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE; + desc = handshake_failure; + goto alert_loser; + } + + rv = ssl3_ConsumeHandshakeVariable(ss, &ec_point, 1, &b, &length); + if (rv != SECSuccess) { + goto loser; /* malformed. */ + } + /* Fail if the ec point uses compressed representation */ + if (ec_point.data[0] != EC_POINT_FORM_UNCOMPRESSED) { + errCode = SEC_ERROR_UNSUPPORTED_EC_POINT_FORM; + desc = handshake_failure; + goto alert_loser; + } + + rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length); + if (rv != SECSuccess) { + goto loser; /* malformed. */ + } + + if (length != 0) { + if (isTLS) + desc = decode_error; + goto alert_loser; /* malformed. */ + } + + PRINT_BUF(60, (NULL, "Server EC params", ec_params.data, + ec_params.len)); + PRINT_BUF(60, (NULL, "Server EC point", ec_point.data, ec_point.len)); + + /* failures after this point are not malformed handshakes. */ + /* TLS: send decrypt_error if signature failed. */ + desc = isTLS ? decrypt_error : handshake_failure; + + /* + * check to make sure the hash is signed by right guy + */ + rv = ssl3_ComputeECDHKeyHash(ec_params, ec_point, + &ss->ssl3.hs.client_random, + &ss->ssl3.hs.server_random, + &hashes, ss->opt.bypassPKCS11); + + if (rv != SECSuccess) { + errCode = + ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); + goto alert_loser; + } + rv = ssl3_VerifySignedHashes(&hashes, ss->sec.peerCert, &signature, + isTLS, ss->pkcs11PinArg); + if (rv != SECSuccess) { + errCode = + ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); + goto alert_loser; + } + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) { + goto no_memory; + } + + ss->sec.peerKey = peerKey = PORT_ArenaZNew(arena, SECKEYPublicKey); + if (peerKey == NULL) { + goto no_memory; + } + + peerKey->arena = arena; + peerKey->keyType = ecKey; + + /* set up EC parameters in peerKey */ + if (ecName2params(arena, ec_params.data[1], + &peerKey->u.ec.DEREncodedParams) != SECSuccess) { + /* we should never get here since we already + * checked that we are dealing with a supported curve + */ + errCode = SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE; + goto alert_loser; + } + + /* copy publicValue in peerKey */ + if (SECITEM_CopyItem(arena, &peerKey->u.ec.publicValue, &ec_point)) + { + PORT_FreeArena(arena, PR_FALSE); + goto no_memory; + } + peerKey->pkcs11Slot = NULL; + peerKey->pkcs11ID = CK_INVALID_HANDLE; + + ss->sec.peerKey = peerKey; + ss->ssl3.hs.ws = wait_cert_request; + + return SECSuccess; + +alert_loser: + (void)SSL3_SendAlert(ss, alert_fatal, desc); +loser: + PORT_SetError( errCode ); + return SECFailure; + +no_memory: /* no-memory error has already been set. */ + ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); + return SECFailure; +} + +SECStatus +ssl3_SendECDHServerKeyExchange(sslSocket *ss) +{ +const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def; + SECStatus rv = SECFailure; + int length; + PRBool isTLS; + SECItem signed_hash = {siBuffer, NULL, 0}; + SSL3Hashes hashes; + + SECKEYPublicKey * ecdhePub; + SECItem ec_params = {siBuffer, NULL, 0}; + ECName curve; + SSL3KEAType certIndex; + + + /* Generate ephemeral ECDH key pair and send the public key */ + rv = ssl3_CreateECDHEphemeralKeys(ss); + if (rv != SECSuccess) { + goto loser; /* err set by AppendHandshake. */ + } + ecdhePub = ss->ephemeralECDHKeyPair->pubKey; + PORT_Assert(ecdhePub != NULL); + if (!ecdhePub) { + PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); + return SECFailure; + } + + ec_params.len = 2; + ec_params.data = (unsigned char*)PORT_Alloc(ec_params.len); + curve = params2ecName(&ecdhePub->u.ec.DEREncodedParams); + if (curve != ec_noName) { + ec_params.data[0] = ec_type_named; + ec_params.data[1] = curve; + } else { + PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); + goto loser; + } + + rv = ssl3_ComputeECDHKeyHash(ec_params, ecdhePub->u.ec.publicValue, + &ss->ssl3.hs.client_random, + &ss->ssl3.hs.server_random, + &hashes, ss->opt.bypassPKCS11); + if (rv != SECSuccess) { + ssl_MapLowLevelError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); + goto loser; + } + + isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); + + /* XXX SSLKEAType isn't really a good choice for + * indexing certificates but that's all we have + * for now. + */ + if (kea_def->kea == kea_ecdhe_rsa) + certIndex = kt_rsa; + else /* kea_def->kea == kea_ecdhe_ecdsa */ + certIndex = kt_ecdh; + + rv = ssl3_SignHashes(&hashes, ss->serverCerts[certIndex].SERVERKEY, + &signed_hash, isTLS); + if (rv != SECSuccess) { + goto loser; /* ssl3_SignHashes has set err. */ + } + if (signed_hash.data == NULL) { + /* how can this happen and rv == SECSuccess ?? */ + PORT_SetError(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE); + goto loser; + } + + length = ec_params.len + + 1 + ecdhePub->u.ec.publicValue.len + + 2 + signed_hash.len; + + rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length); + if (rv != SECSuccess) { + goto loser; /* err set by AppendHandshake. */ + } + + rv = ssl3_AppendHandshake(ss, ec_params.data, ec_params.len); + if (rv != SECSuccess) { + goto loser; /* err set by AppendHandshake. */ + } + + rv = ssl3_AppendHandshakeVariable(ss, ecdhePub->u.ec.publicValue.data, + ecdhePub->u.ec.publicValue.len, 1); + if (rv != SECSuccess) { + goto loser; /* err set by AppendHandshake. */ + } + + rv = ssl3_AppendHandshakeVariable(ss, signed_hash.data, + signed_hash.len, 2); + if (rv != SECSuccess) { + goto loser; /* err set by AppendHandshake. */ + } + + PORT_Free(ec_params.data); + PORT_Free(signed_hash.data); + return SECSuccess; + +loser: + if (ec_params.data != NULL) + PORT_Free(ec_params.data); + if (signed_hash.data != NULL) + PORT_Free(signed_hash.data); + return SECFailure; +} + + +#endif /* NSS_ENABLE_ECC */ + diff --git a/security/nss/lib/ssl/ssl3gthr.c b/security/nss/lib/ssl/ssl3gthr.c index 7fbf7663e..4465c4359 100644 --- a/security/nss/lib/ssl/ssl3gthr.c +++ b/security/nss/lib/ssl/ssl3gthr.c @@ -72,7 +72,7 @@ ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags) int err; int rv = 1; - PORT_Assert( ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); if (gs->state == GS_INIT) { gs->state = GS_HEADER; gs->remainder = 5; @@ -189,7 +189,7 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) SSL3Ciphertext cText; int rv; - PORT_Assert( ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); do { /* bring in the next sslv3 record. */ rv = ssl3_GatherData(ss, &ss->gs, flags); @@ -207,7 +207,7 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) if (rv < 0) { return ss->recvdCloseNotify ? 0 : rv; } - } while (ss->ssl3->hs.ws != idle_handshake && ss->gs.buf.len == 0); + } while (ss->ssl3.hs.ws != idle_handshake && ss->gs.buf.len == 0); ss->gs.readOffset = 0; ss->gs.writeOffset = ss->gs.buf.len; @@ -230,7 +230,7 @@ ssl3_GatherAppDataRecord(sslSocket *ss, int flags) { int rv; - PORT_Assert( ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); do { rv = ssl3_GatherCompleteHandshake(ss, flags); } while (rv > 0 && ss->gs.buf.len == 0); diff --git a/security/nss/lib/ssl/ssl3prot.h b/security/nss/lib/ssl/ssl3prot.h index c68fa8270..d466c614d 100644 --- a/security/nss/lib/ssl/ssl3prot.h +++ b/security/nss/lib/ssl/ssl3prot.h @@ -1,4 +1,4 @@ -/* +/* Private header file of libSSL. * Various and sundry protocol constants. DON'T CHANGE THESE. These * values are defined by the SSL 3.0 protocol specification. * @@ -206,7 +206,6 @@ typedef enum { kea_dhe_rsa_export, kea_dh_anon, kea_dh_anon_export, - kea_fortezza, kea_rsa_fips, kea_ecdh_ecdsa, kea_ecdhe_ecdsa, @@ -257,9 +256,8 @@ typedef enum { */ ct_ECDSA_sign = 7, ct_RSA_fixed_ECDH = 8, - ct_ECDSA_fixed_ECDH = 9, + ct_ECDSA_fixed_ECDH = 9 - ct_Fortezza = 20 } SSL3ClientCertificateType; typedef SECItem *SSL3DistinquishedName; @@ -271,18 +269,6 @@ typedef struct { typedef SECItem SSL3EncryptedPreMasterSecret; -/* Following struct is the format of a Fortezza ClientKeyExchange message. */ -typedef struct { - SECItem y_c; - SSL3Opaque r_c [128]; - SSL3Opaque y_signature [40]; - SSL3Opaque wrapped_client_write_key [12]; - SSL3Opaque wrapped_server_write_key [12]; - SSL3Opaque client_write_iv [24]; - SSL3Opaque server_write_iv [24]; - SSL3Opaque master_secret_iv [24]; - SSL3Opaque encrypted_preMasterSecret[48]; -} SSL3FortezzaKeys; typedef SSL3Opaque SSL3MasterSecret[48]; @@ -299,7 +285,6 @@ typedef struct { union { SSL3EncryptedPreMasterSecret rsa; SSL3ClientDiffieHellmanPublic diffie_helman; - SSL3FortezzaKeys fortezza; } exchange_keys; } SSL3ClientKeyExchange; diff --git a/security/nss/lib/ssl/sslauth.c b/security/nss/lib/ssl/sslauth.c index 690008e42..848f5aa63 100644 --- a/security/nss/lib/ssl/sslauth.c +++ b/security/nss/lib/ssl/sslauth.c @@ -53,7 +53,7 @@ SSL_PeerCertificate(PRFileDesc *fd) SSL_GETPID(), fd)); return 0; } - if (ss->useSecurity && ss->sec.peerCert) { + if (ss->opt.useSecurity && ss->sec.peerCert) { return CERT_DupCertificate(ss->sec.peerCert); } return 0; @@ -71,7 +71,7 @@ SSL_LocalCertificate(PRFileDesc *fd) SSL_GETPID(), fd)); return NULL; } - if (ss->useSecurity) { + if (ss->opt.useSecurity) { if (ss->sec.localCert) { return CERT_DupCertificate(ss->sec.localCert); } @@ -109,7 +109,7 @@ SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1, *op = SSL_SECURITY_STATUS_OFF; } - if (ss->useSecurity && ss->firstHsDone) { + if (ss->opt.useSecurity && ss->firstHsDone) { if (ss->version < SSL_LIBRARY_VERSION_3_0) { cipherName = ssl_cipherName[ss->sec.cipherType]; @@ -117,8 +117,7 @@ SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1, cipherName = ssl3_cipherName[ss->sec.cipherType]; } if (cipherName && PORT_Strstr(cipherName, "DES")) isDes = PR_TRUE; - /* do same key stuff for fortezza */ - + if (cp) { *cp = PORT_Strdup(cipherName); } diff --git a/security/nss/lib/ssl/sslcon.c b/security/nss/lib/ssl/sslcon.c index da20986b5..06ec09813 100644 --- a/security/nss/lib/ssl/sslcon.c +++ b/security/nss/lib/ssl/sslcon.c @@ -145,7 +145,7 @@ const char * const ssl_cipherName[] = { "DES-CBC", "DES-EDE3-CBC", "unknown", - "Fortezza", + "unknown", /* was fortezza, NO LONGER USED */ }; @@ -186,11 +186,11 @@ ssl2_ConstructCipherSpecs(sslSocket *ss) int i; SECStatus rv; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); count = 0; PORT_Assert(ss != 0); - allowed = !ss->enableSSL2 ? 0 : + allowed = !ss->opt.enableSSL2 ? 0 : (ss->allowedByPolicy & ss->chosenPreference & SSL_CB_IMPLEMENTED); while (allowed) { if (allowed & 1) @@ -226,7 +226,7 @@ ssl2_ConstructCipherSpecs(sslSocket *ss) ss->sizeCipherSpecs = count * 3; /* fill in cipher specs for SSL2 cipher suites */ - allowed = !ss->enableSSL2 ? 0 : + allowed = !ss->opt.enableSSL2 ? 0 : (ss->allowedByPolicy & ss->chosenPreference & SSL_CB_IMPLEMENTED); for (i = 0; i < ssl2_NUM_SUITES_IMPLEMENTED * 3; i += 3) { const PRUint8 * hs = implementedCipherSuites + i; @@ -271,17 +271,17 @@ ssl2_CheckConfigSanity(sslSocket *ss) allowed = ss->allowedByPolicy & ss->chosenPreference; if (! allowed) - ss->enableSSL2 = PR_FALSE; /* not really enabled if no ciphers */ + ss->opt.enableSSL2 = PR_FALSE; /* not really enabled if no ciphers */ /* ssl3_config_match_init was called in ssl2_ConstructCipherSpecs(). */ /* Ask how many ssl3 CipherSuites were enabled. */ rv = ssl3_ConstructV2CipherSpecsHack(ss, NULL, &ssl3CipherCount); if (rv != SECSuccess || ssl3CipherCount <= 0) { - ss->enableSSL3 = PR_FALSE; /* not really enabled if no ciphers */ - ss->enableTLS = PR_FALSE; + ss->opt.enableSSL3 = PR_FALSE; /* not really enabled if no ciphers */ + ss->opt.enableTLS = PR_FALSE; } - if (!ss->enableSSL2 && !ss->enableSSL3 && !ss->enableTLS) { + if (!ss->opt.enableSSL2 && !ss->opt.enableSSL3 && !ss->opt.enableTLS) { SSL_DBG(("%d: SSL[%d]: Can't handshake! both v2 and v3 disabled.", SSL_GETPID(), ss->fd)); disabled: @@ -495,7 +495,7 @@ ssl2_GetSendBuffer(sslSocket *ss, unsigned int len) { SECStatus rv = SECSuccess; - PORT_Assert(ssl_HaveXmitBufLock(ss)); + PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); if (len < 128) { len = 128; @@ -530,7 +530,7 @@ ssl2_SendErrorMessage(sslSocket *ss, int error) int rv; PRUint8 msg[SSL_HL_ERROR_HBYTES]; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); msg[0] = SSL_MT_ERROR; msg[1] = MSB(error); @@ -559,7 +559,7 @@ ssl2_SendClientFinishedMessage(sslSocket *ss) int sent; PRUint8 msg[1 + SSL_CONNECTIONID_BYTES]; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); ssl_GetXmitBufLock(ss); /***************************************/ @@ -595,7 +595,7 @@ ssl2_SendServerVerifyMessage(sslSocket *ss) int sent; SECStatus rv; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); ssl_GetXmitBufLock(ss); /***************************************/ @@ -630,7 +630,7 @@ ssl2_SendServerFinishedMessage(sslSocket *ss) int sendLen, sent; SECStatus rv = SECSuccess; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); ssl_GetXmitBufLock(ss); /***************************************/ @@ -660,7 +660,7 @@ ssl2_SendServerFinishedMessage(sslSocket *ss) /* If send failed, it is now a bogus session-id */ (*ss->sec.uncache)(sid); rv = (SECStatus)sent; - } else if (!ss->noCache) { + } else if (!ss->opt.noCache) { /* Put the sid in session-id cache, (may already be there) */ (*ss->sec.cache)(sid); rv = SECSuccess; @@ -689,7 +689,7 @@ ssl2_SendSessionKeyMessage(sslSocket *ss, int cipher, int keySize, int sent; SECStatus rv; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); ssl_GetXmitBufLock(ss); /***************************************/ @@ -735,7 +735,7 @@ ssl2_SendCertificateRequestMessage(sslSocket *ss) int sendLen; SECStatus rv; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); ssl_GetXmitBufLock(ss); /***************************************/ @@ -775,7 +775,7 @@ ssl2_SendCertificateResponseMessage(sslSocket *ss, SECItem *cert, PRUint8 *msg; int rv, sendLen; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); ssl_GetXmitBufLock(ss); /***************************************/ @@ -887,7 +887,7 @@ ssl2_SendClear(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags) int amount; int count = 0; - PORT_Assert( ssl_HaveXmitBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); SSL_TRC(10, ("%d: SSL[%d]: sending %d bytes in the clear", SSL_GETPID(), ss->fd, len)); @@ -962,7 +962,7 @@ ssl2_SendStream(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags) int nout; int buflen; - PORT_Assert( ssl_HaveXmitBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); SSL_TRC(10, ("%d: SSL[%d]: sending %d bytes using stream cipher", SSL_GETPID(), ss->fd, len)); @@ -1067,7 +1067,7 @@ ssl2_SendBlock(sslSocket *ss, const PRUint8 *in, PRInt32 len, PRInt32 flags) int nout; /* ciphertext size after header. */ int buflen; /* size of generated record. */ - PORT_Assert( ssl_HaveXmitBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); SSL_TRC(10, ("%d: SSL[%d]: sending %d bytes using block cipher", SSL_GETPID(), ss->fd, len)); @@ -1251,7 +1251,7 @@ ssl_GatherRecord1stHandshake(sslSocket *ss) { int rv; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); ssl_GetRecvBufLock(ss); @@ -1369,7 +1369,7 @@ ssl2_ProduceKeys(sslSocket * ss, readKey->data = 0; writeKey->data = 0; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); rv = SECSuccess; cx = PK11_CreateDigestContext(SEC_OID_MD5); @@ -1441,7 +1441,7 @@ ssl2_CreateSessionCypher(sslSocket *ss, sslSessionID *sid, PRBool isClient) readKey.data = 0; writeKey.data = 0; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); if((ss->sec.ci.sid == 0)) goto sec_loser; /* don't crash if asserts are off */ @@ -1591,9 +1591,9 @@ ssl2_ServerSetupSessionCypher(sslSocket *ss, int cipher, unsigned int keyBits, PRUint8 mkbuf[SSL_MAX_MASTER_KEY_BYTES]; sslServerCerts * sc = ss->serverCerts + kt_rsa; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert((sc->serverKey != 0)); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert((sc->SERVERKEY != 0)); PORT_Assert((ss->sec.ci.sid != 0)); sid = ss->sec.ci.sid; @@ -1651,11 +1651,11 @@ ssl2_ServerSetupSessionCypher(sslSocket *ss, int cipher, unsigned int keyBits, ** NOTE: PK11_PubDecryptRaw will barf on a non-RSA key. This is ** desired behavior here. */ - rv = PK11_PubDecryptRaw(sc->serverKey, kbuf, &el1, ekLen, ek, ekLen); + rv = PK11_PubDecryptRaw(sc->SERVERKEY, kbuf, &el1, ekLen, ek, ekLen); if (rv != SECSuccess) goto hide_loser; - modulusLen = PK11_GetPrivateModulusLen(sc->serverKey); + modulusLen = PK11_GetPrivateModulusLen(sc->SERVERKEY); if (modulusLen == -1) { /* If the key was really bad, then PK11_pubDecryptRaw * would have failed, therefore the we must assume that the card @@ -1679,7 +1679,7 @@ ssl2_ServerSetupSessionCypher(sslSocket *ss, int cipher, unsigned int keyBits, } /* Make sure we're not subject to a version rollback attack. */ - if (ss->enableSSL3 || ss->enableTLS) { + if (ss->opt.enableSSL3 || ss->opt.enableTLS) { PRUint8 threes[8] = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }; @@ -1763,8 +1763,8 @@ ssl2_QualifyCypherSpecs(sslSocket *ss, int hc; PRUint8 qualifiedSpecs[ssl2_NUM_SUITES_IMPLEMENTED * 3]; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); - PORT_Assert( ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); if (!ss->cipherSpecs) { ssl2_ConstructCipherSpecs(ss); @@ -1824,8 +1824,8 @@ ssl2_ChooseSessionCypher(sslSocket *ss, int realKeySize; PRUint8 * ohs = hs; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); - PORT_Assert( ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); if (!ss->cipherSpecs) { ssl2_ConstructCipherSpecs(ss); @@ -2044,7 +2044,7 @@ ssl2_ClientSetupSessionCypher(sslSocket *ss, PRUint8 *cs, int csLen) PRUint8 keyData[SSL_MAX_MASTER_KEY_BYTES]; PRUint8 iv [8]; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); eblock = NULL; @@ -2131,7 +2131,7 @@ ssl2_ClientSetupSessionCypher(sslSocket *ss, PRUint8 *cs, int csLen) /* Set up the padding for version 2 rollback detection. */ /* XXX We should really use defines here */ - if (ss->enableSSL3 || ss->enableTLS) { + if (ss->opt.enableSSL3 || ss->opt.enableTLS) { PORT_Assert((modulusLen - rek.len) > 12); PORT_Memset(eblock + modulusLen - rek.len - 8 - 1, 0x03, 8); } @@ -2185,7 +2185,7 @@ ssl2_ClientRegSessionID(sslSocket *ss, PRUint8 *s) sid->peerCert = CERT_DupCertificate(ss->sec.peerCert); } - if (!ss->noCache) + if (!ss->opt.noCache) (*ss->sec.cache)(sid); } @@ -2195,7 +2195,7 @@ ssl2_TriggerNextMessage(sslSocket *ss) { SECStatus rv; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); if ((ss->sec.ci.requiredElements & CIS_HAVE_CERTIFICATE) && !(ss->sec.ci.sentElements & CIS_HAVE_CERTIFICATE)) { @@ -2223,7 +2223,7 @@ ssl2_TryToFinish(sslSocket *ss) SECStatus rv; char e, ef; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); e = ss->sec.ci.elements; ef = e | CIS_HAVE_FINISHED; @@ -2261,7 +2261,7 @@ ssl2_SignResponse(sslSocket *ss, unsigned int len; SECStatus rv = SECFailure; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); challenge = ss->sec.ci.serverChallenge; len = ss->sec.ci.serverChallengeLen; @@ -2424,8 +2424,8 @@ ssl2_HandleClientCertificate(sslSocket * ss, SECItem certItem; SECItem rep; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); - PORT_Assert( ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); /* Extract the certificate */ certItem.data = cd; @@ -2512,7 +2512,7 @@ ssl2_HandleMessage(sslSocket *ss) int rv; int rv2; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); ssl_GetRecvBufLock(ss); @@ -2706,7 +2706,7 @@ ssl2_HandleVerifyMessage(sslSocket *ss) PRUint8 * data; SECStatus rv; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); ssl_GetRecvBufLock(ss); data = ss->gs.buf.buf + ss->gs.recordOffset; @@ -2758,9 +2758,9 @@ ssl2_HandleServerHelloMessage(sslSocket *ss) SECStatus rv; int needed, sidHit, certLen, csLen, cidLen, certType, err; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); - if (!ss->enableSSL2) { + if (!ss->opt.enableSSL2) { PORT_SetError(SSL_ERROR_SSL2_DISABLED); return SECFailure; } @@ -2989,7 +2989,7 @@ ssl2_BeginClientHandshake(sslSocket *ss) int sendLen, sidLen = 0; SECStatus rv; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); ss->sec.isServer = 0; ss->sec.sendSequence = 0; @@ -3035,7 +3035,7 @@ ssl2_BeginClientHandshake(sslSocket *ss) SSL_TRC(3, ("%d: SSL[%d]: sending client-hello", SSL_GETPID(), ss->fd)); /* Try to find server in our session-id cache */ - if (ss->noCache) { + if (ss->opt.noCache) { sid = NULL; } else { sid = ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID, @@ -3043,15 +3043,15 @@ ssl2_BeginClientHandshake(sslSocket *ss) } while (sid) { /* this isn't really a loop */ /* if we're not doing this SID's protocol any more, drop it. */ - if (((sid->version < SSL_LIBRARY_VERSION_3_0) && !ss->enableSSL2) || - ((sid->version == SSL_LIBRARY_VERSION_3_0) && !ss->enableSSL3) || - ((sid->version > SSL_LIBRARY_VERSION_3_0) && !ss->enableTLS)) { + if (((sid->version < SSL_LIBRARY_VERSION_3_0) && !ss->opt.enableSSL2) || + ((sid->version == SSL_LIBRARY_VERSION_3_0) && !ss->opt.enableSSL3) || + ((sid->version > SSL_LIBRARY_VERSION_3_0) && !ss->opt.enableTLS)) { ss->sec.uncache(sid); ssl_FreeSID(sid); sid = NULL; break; } - if (ss->enableSSL2 && sid->version < SSL_LIBRARY_VERSION_3_0) { + if (ss->opt.enableSSL2 && sid->version < SSL_LIBRARY_VERSION_3_0) { /* If the cipher in this sid is not enabled, drop it. */ for (i = 0; i < ss->sizeCipherSpecs; i += 3) { if (ss->cipherSpecs[i] == sid->u.ssl2.cipherType) @@ -3096,8 +3096,8 @@ ssl2_BeginClientHandshake(sslSocket *ss) PORT_Assert(sid != NULL); - if ((sid->version >= SSL_LIBRARY_VERSION_3_0 || !ss->v2CompatibleHello) && - (ss->enableSSL3 || ss->enableTLS)) { + if ((sid->version >= SSL_LIBRARY_VERSION_3_0 || !ss->opt.v2CompatibleHello) && + (ss->opt.enableSSL3 || ss->opt.enableTLS)) { ss->gs.state = GS_INIT; ss->handshake = ssl_GatherRecord1stHandshake; @@ -3138,9 +3138,9 @@ ssl2_BeginClientHandshake(sslSocket *ss) /* Construct client-hello message */ cp = msg = ss->sec.ci.sendBuf.buf; msg[0] = SSL_MT_CLIENT_HELLO; - if ( ss->enableTLS ) { + if ( ss->opt.enableTLS ) { ss->clientHelloVersion = SSL_LIBRARY_VERSION_3_1_TLS; - } else if ( ss->enableSSL3 ) { + } else if ( ss->opt.enableSSL3 ) { ss->clientHelloVersion = SSL_LIBRARY_VERSION_3_0; } else { ss->clientHelloVersion = SSL_LIBRARY_VERSION_2; @@ -3441,7 +3441,7 @@ ssl2_HandleClientHelloMessage(sslSocket *ss) #endif PRUint8 csImpl[sizeof implementedCipherSuites]; - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); sc = ss->serverCerts + kt_rsa; serverCert = sc->serverCert; @@ -3470,7 +3470,7 @@ ssl2_HandleClientHelloMessage(sslSocket *ss) */ if ((data[0] == SSL_MT_CLIENT_HELLO) && (data[1] >= MSB(SSL_LIBRARY_VERSION_3_0)) && - (ss->enableSSL3 || ss->enableTLS)) { + (ss->opt.enableSSL3 || ss->opt.enableTLS)) { rv = ssl3_HandleV2ClientHello(ss, data, ss->gs.recordLen); if (rv != SECFailure) { /* Success */ ss->handshake = NULL; @@ -3558,7 +3558,7 @@ ssl2_HandleClientHelloMessage(sslSocket *ss) goto loser; } /* Since this handhsake is going to fail, don't cache it. */ - ss->noCache = 1; + ss->opt.noCache = 1; } /* Squirrel away the challenge for later */ @@ -3566,7 +3566,7 @@ ssl2_HandleClientHelloMessage(sslSocket *ss) /* Examine message and see if session-id is good */ ss->sec.ci.elements = 0; - if (sdLen > 0 && !ss->noCache) { + if (sdLen > 0 && !ss->opt.noCache) { SSL_TRC(7, ("%d: SSL[%d]: server, lookup client session-id for 0x%08x%08x%08x%08x", SSL_GETPID(), ss->fd, ss->sec.ci.peer.pr_s6_addr32[0], ss->sec.ci.peer.pr_s6_addr32[1], @@ -3648,7 +3648,7 @@ ssl2_HandleClientHelloMessage(sslSocket *ss) /* Build up final list of required elements */ ss->sec.ci.requiredElements = CIS_HAVE_MASTER_KEY | CIS_HAVE_FINISHED; - if (ss->requestCertificate) { + if (ss->opt.requestCertificate) { ss->sec.ci.requiredElements |= CIS_HAVE_CERTIFICATE; } ss->sec.ci.sentElements = 0; @@ -3742,8 +3742,8 @@ ssl2_BeginServerHandshake(sslSocket *ss) ss->sec.rcvSequence = 0; /* don't turn on SSL2 if we don't have an RSA key and cert */ - if (!rsaAuth->serverKey || !rsaAuth->serverCert) { - ss->enableSSL2 = PR_FALSE; + if (!rsaAuth->SERVERKEY || !rsaAuth->serverCert) { + ss->opt.enableSSL2 = PR_FALSE; } if (!ss->cipherSpecs) { diff --git a/security/nss/lib/ssl/ssldef.c b/security/nss/lib/ssl/ssldef.c index d42da2956..23ef9cafe 100644 --- a/security/nss/lib/ssl/ssldef.c +++ b/security/nss/lib/ssl/ssldef.c @@ -117,7 +117,7 @@ int ssl_DefSend(sslSocket *ss, const unsigned char *buf, int len, int flags) /* Although this is overkill, we disable Nagle delays completely for ** SSL sockets. */ - if (ss->useSecurity && !ss->delayDisabled) { + if (ss->opt.useSecurity && !ss->delayDisabled) { ssl_EnableNagleDelay(ss, PR_FALSE); /* ignore error */ ss->delayDisabled = 1; } diff --git a/security/nss/lib/ssl/sslenum.c b/security/nss/lib/ssl/sslenum.c index 2745155af..d28d689b7 100644 --- a/security/nss/lib/ssl/sslenum.c +++ b/security/nss/lib/ssl/sslenum.c @@ -56,7 +56,6 @@ const PRUint16 SSL_ImplementedCiphers[] = { TLS_RSA_WITH_AES_256_CBC_SHA, /* 128-bit */ - SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, #ifdef NSS_ENABLE_ECC TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, @@ -84,9 +83,6 @@ const PRUint16 SSL_ImplementedCiphers[] = { SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, - /* 80 bit skipjack */ - SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, /* KEA + SkipJack */ - /* 56-bit DES "domestic" cipher suites */ SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, @@ -106,7 +102,6 @@ const PRUint16 SSL_ImplementedCiphers[] = { SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, /* ciphersuites with no encryption */ - SSL_FORTEZZA_DMS_WITH_NULL_SHA, #ifdef NSS_ENABLE_ECC TLS_ECDH_RSA_WITH_NULL_SHA, TLS_ECDH_ECDSA_WITH_NULL_SHA, diff --git a/security/nss/lib/ssl/sslgathr.c b/security/nss/lib/ssl/sslgathr.c index 75c465099..8308ad194 100644 --- a/security/nss/lib/ssl/sslgathr.c +++ b/security/nss/lib/ssl/sslgathr.c @@ -90,7 +90,7 @@ ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags) unsigned char * pBuf; int nb, err, rv; - PORT_Assert( ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); if (gs->state == GS_INIT) { /* Initialize gathering engine */ @@ -141,9 +141,9 @@ ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags) /* Probably finished this piece */ switch (gs->state) { case GS_HEADER: - if ((ss->enableSSL3 || ss->enableTLS) && !ss->firstHsDone) { + if ((ss->opt.enableSSL3 || ss->opt.enableTLS) && !ss->firstHsDone) { - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); /* If this looks like an SSL3 handshake record, ** and we're expecting an SSL2 Hello message from our peer, @@ -185,7 +185,7 @@ ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags) return SECFailure; } } - } /* ((ss->enableSSL3 || ss->enableTLS) && !ss->firstHsDone) */ + } /* ((ss->opt.enableSSL3 || ss->opt.enableTLS) && !ss->firstHsDone) */ /* we've got the first 3 bytes. The header may be two or three. */ if (gs->hdr[0] & 0x80) { @@ -411,7 +411,7 @@ ssl2_StartGatherBytes(sslSocket *ss, sslGather *gs, unsigned int count) { int rv; - PORT_Assert( ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); gs->state = GS_DATA; gs->remainder = count; gs->count = count; @@ -455,8 +455,8 @@ ssl2_HandleV3HandshakeRecord(sslSocket *ss) SECStatus rv; SSL3ProtocolVersion version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2]; - PORT_Assert( ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); /* We've read in 3 bytes, there are 2 more to go in an ssl3 header. */ ss->gs.remainder = 2; diff --git a/security/nss/lib/ssl/sslimpl.h b/security/nss/lib/ssl/sslimpl.h index f42bd4be3..1da55d59b 100644 --- a/security/nss/lib/ssl/sslimpl.h +++ b/security/nss/lib/ssl/sslimpl.h @@ -84,7 +84,7 @@ typedef SSLSignType SSL3SignType; #define calg_des ssl_calg_des #define calg_3des ssl_calg_3des #define calg_idea ssl_calg_idea -#define calg_fortezza ssl_calg_fortezza +#define calg_fortezza ssl_calg_fortezza /* deprecated, must preserve */ #define calg_aes ssl_calg_aes #define mac_null ssl_mac_null @@ -93,6 +93,10 @@ typedef SSLSignType SSL3SignType; #define hmac_md5 ssl_hmac_md5 #define hmac_sha ssl_hmac_sha +#define SET_ERROR_CODE /* reminder */ +#define SEND_ALERT /* reminder */ +#define TEST_FOR_FAILURE /* reminder */ +#define DEAL_WITH_FAILURE /* reminder */ #if defined(DEBUG) || defined(TRACE) #ifdef __cplusplus @@ -162,12 +166,17 @@ typedef enum { SSLAppOpRead = 0, #define SSL_MAX_MAC_BYTES 16 +#define SSL3_RSA_PMS_LENGTH 48 +#define SSL3_MASTER_SECRET_LENGTH 48 + /* number of wrap mechanisms potentially used to wrap master secrets. */ #define SSL_NUM_WRAP_MECHS 13 /* This makes the cert cache entry exactly 4k. */ #define SSL_MAX_CACHED_CERT_LEN 4060 +#define NUM_MIXERS 9 + #ifndef BPB #define BPB 8 /* Bits Per Byte */ #endif @@ -261,9 +270,9 @@ typedef struct { } ssl3CipherSuiteCfg; #ifdef NSS_ENABLE_ECC -#define ssl_V3_SUITES_IMPLEMENTED 40 +#define ssl_V3_SUITES_IMPLEMENTED 37 #else -#define ssl_V3_SUITES_IMPLEMENTED 26 +#define ssl_V3_SUITES_IMPLEMENTED 23 #endif /* NSS_ENABLE_ECC */ typedef struct sslOptionsStr { @@ -281,6 +290,8 @@ typedef struct sslOptionsStr { unsigned int v2CompatibleHello : 1; /* 13 */ unsigned int detectRollBack : 1; /* 14 */ unsigned int noStepDown : 1; /* 15 */ + unsigned int bypassPKCS11 : 1; /* 16 */ + unsigned int noLocks : 1; /* 17 */ } sslOptions; typedef enum { sslHandshakingUndetermined = 0, @@ -292,10 +303,11 @@ typedef struct sslServerCertsStr { /* Configuration state for server sockets */ CERTCertificate * serverCert; CERTCertificateList * serverCertChain; - SECKEYPrivateKey * serverKey; + ssl3KeyPair * serverKeyPair; unsigned int serverKeyBits; } sslServerCerts; +#define SERVERKEY serverKeyPair->privKey #define SSL_LOCK_RANK_SPEC 255 #define SSL_LOCK_RANK_GLOBAL NSS_RWLOCK_RANK_NONE @@ -414,7 +426,6 @@ typedef enum { cipher_3des, cipher_des40, cipher_idea, - cipher_fortezza, cipher_aes_128, cipher_aes_256, cipher_missing /* reserved for no such supported cipher */ @@ -433,21 +444,31 @@ typedef struct { uint32 low; } SSL3SequenceNumber; -typedef struct { - SSL3Opaque write_iv[MAX_IV_LENGTH]; - PK11SymKey *write_key; - PK11SymKey *write_mac_key; - PK11Context *write_mac_context; -} ssl3KeyMaterial; +#define MAX_MAC_CONTEXT_BYTES 400 +#define MAX_MAC_CONTEXT_LLONGS (MAX_MAC_CONTEXT_BYTES / 8) + +#define MAX_CIPHER_CONTEXT_BYTES 2080 +#define MAX_CIPHER_CONTEXT_LLONGS (MAX_CIPHER_CONTEXT_BYTES / 8) typedef struct { - SSL3Opaque wrapped_client_write_key[12]; /* wrapped with Ks */ - SSL3Opaque wrapped_server_write_key[12]; /* wrapped with Ks */ SSL3Opaque client_write_iv [24]; SSL3Opaque server_write_iv [24]; SSL3Opaque wrapped_master_secret [48]; PRUint16 wrapped_master_secret_len; -} ssl3SidKeys; + PRUint8 msIsWrapped; + PRUint8 resumable; +} ssl3SidKeys; /* 100 bytes */ + +typedef struct { + PK11SymKey *write_key; + PK11SymKey *write_mac_key; + PK11Context *write_mac_context; + SECItem write_key_item; + SECItem write_iv_item; + SECItem write_mac_key_item; + SSL3Opaque write_iv[MAX_IV_LENGTH]; + PRUint64 cipher_context[MAX_CIPHER_CONTEXT_LLONGS]; +} ssl3KeyMaterial; /* ** These are the "specs" in the "ssl3" struct. @@ -459,16 +480,20 @@ typedef struct { const ssl3MACDef * mac_def; int mac_size; SSLCipher encode; - void * encodeContext; SSLCipher decode; - void * decodeContext; SSLDestroy destroy; + void * encodeContext; + void * decodeContext; + PRBool bypassCiphers; /* did double bypass (at least) */ PK11SymKey * master_secret; - ssl3KeyMaterial client; - ssl3KeyMaterial server; SSL3SequenceNumber write_seq_num; SSL3SequenceNumber read_seq_num; SSL3ProtocolVersion version; + ssl3KeyMaterial client; + ssl3KeyMaterial server; + SECItem msItem; + unsigned char key_block[NUM_MIXERS * MD5_LENGTH]; + unsigned char raw_master_secret[56]; } ssl3CipherSpec; typedef enum { never_cached, @@ -520,9 +545,7 @@ struct sslSessionIDStr { ssl3CipherSuite cipherSuite; SSL3CompressionMethod compression; - PRBool resumable; int policy; - PRBool hasFortezza; ssl3SidKeys keys; CK_MECHANISM_TYPE masterWrapMech; /* mechanism used to wrap master secret */ @@ -535,7 +558,6 @@ struct sslSessionIDStr { */ PK11SymKey * clientWriteKey; PK11SymKey * serverWriteKey; - PK11SymKey * tek; /* The following values pertain to the slot that wrapped the ** master secret. (used only in client) @@ -560,11 +582,6 @@ struct sslSessionIDStr { char masterValid; char clAuthValid; - /* the following values are used only in the client, and only - * with fortezza. - */ - SSL3Opaque clientWriteSave[80]; - int clientWriteSaveLen; } ssl3; } u; }; @@ -638,6 +655,8 @@ typedef struct SSL3HandshakeStateStr { SSL3Random server_random; SSL3Random client_random; SSL3WaitState ws; + PRUint64 md5_cx[MAX_MAC_CONTEXT_LLONGS]; + PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS]; PK11Context * md5; /* handshake running hashes */ PK11Context * sha; const ssl3KEADef * kea_def; @@ -660,12 +679,7 @@ const ssl3CipherSuiteDef *suite_def; /* protected by recvBufLock */ } SSL3HandshakeState; -struct SSL3FortezzaKEAParamsStr { - unsigned char R_s[128]; /* server's "random" public key */ - PK11SymKey * tek; -}; -typedef struct SSL3FortezzaKEAParamsStr SSL3FortezzaKEAParams; /* ** This is the "ssl3" struct, as in "ss->ssl3". @@ -685,9 +699,6 @@ struct ssl3StateStr { ssl3CipherSpec * prSpec; /* pending read spec. */ ssl3CipherSpec * cwSpec; /* current write spec. */ ssl3CipherSpec * pwSpec; /* pending write spec. */ - ssl3CipherSpec specs[2]; /* one is current, one is pending. */ - - SSL3HandshakeState hs; CERTCertificate * clientCertificate; /* used by client */ SECKEYPrivateKey * clientPrivateKey; /* used by client */ @@ -704,7 +715,9 @@ struct ssl3StateStr { /* chain while we are trying to validate it. */ CERTDistNames * ca_list; /* used by server. trusted CAs for this socket. */ - SSL3FortezzaKEAParams fortezza; + PRBool initialized; + SSL3HandshakeState hs; + ssl3CipherSpec specs[2]; /* one is current, one is pending. */ }; typedef struct { @@ -751,7 +764,7 @@ typedef struct SSLWrappedSymWrappingKeyStr { */ /* -** This is "ci", as in "ss->sec->ci". +** This is "ci", as in "ss->sec.ci". ** ** Protection: All the variables in here are protected by ** firstHandshakeLock AND (in ssl3) ssl3HandshakeLock @@ -873,30 +886,17 @@ struct sslSocketStr { /* Pointer to operations vector for this socket */ const sslSocketOps * ops; + /* SSL socket options */ + sslOptions opt; + /* State flags */ - unsigned int useSocks : 1; - unsigned int useSecurity : 1; - unsigned int requestCertificate : 1; - unsigned int requireCertificate : 2; - unsigned int handshakeAsClient : 1; - unsigned int handshakeAsServer : 1; - unsigned int enableSSL2 : 1; - - unsigned int enableSSL3 : 1; - unsigned int enableTLS : 1; - unsigned int clientAuthRequested: 1; - unsigned int noCache : 1; - unsigned int fdx : 1; /* simultaneous R/W threads */ - unsigned int v2CompatibleHello : 1; /* Send v3+ client hello in v2 format */ - unsigned int detectRollBack : 1; /* Detect rollback to SSL v3 */ - unsigned int firstHsDone : 1; /* first handshake is complete. */ - - unsigned int recvdCloseNotify : 1; /* received SSL EOF. */ - unsigned int lastWriteBlocked : 1; - unsigned int TCPconnected : 1; - unsigned int handshakeBegun : 1; - unsigned int delayDisabled : 1; /* Nagle delay disabled */ - unsigned int noStepDown : 1; + unsigned long clientAuthRequested; + unsigned long delayDisabled; /* Nagle delay disabled */ + unsigned long firstHsDone; /* first handshake is complete. */ + unsigned long handshakeBegun; + unsigned long lastWriteBlocked; + unsigned long recvdCloseNotify; /* received SSL EOF. */ + unsigned long TCPconnected; /* version of the protocol to use */ SSL3ProtocolVersion version; @@ -907,28 +907,17 @@ struct sslSocketStr { /* protected by firstHandshakeLock AND (in ssl3) ssl3HandshakeLock. */ const char *url; /* ssl 2 & 3 */ - /* Gather object used for gathering data */ - sslGather gs; /*recvBufLock*/ - sslHandshakeFunc handshake; /*firstHandshakeLock*/ sslHandshakeFunc nextHandshake; /*firstHandshakeLock*/ sslHandshakeFunc securityHandshake; /*firstHandshakeLock*/ - sslBuffer saveBuf; /*xmitBufLock*/ - sslBuffer pendingBuf; /*xmitBufLock*/ - /* the following variable is only used with socks or other proxies. */ char * peerID; /* String uniquely identifies target server. */ - ssl3State * ssl3; unsigned char * cipherSpecs; unsigned int sizeCipherSpecs; const unsigned char * preferredCipher; - /* Configuration state for server sockets */ - /* server cert and key for each KEA type */ - sslServerCerts serverCerts[kt_kea_size]; - ssl3KeyPair * stepDownKeyPair; /* RSA step down keys */ /* Callbacks */ @@ -983,8 +972,21 @@ const unsigned char * preferredCipher; sslHandshakingType handshaking; + /* Gather object used for gathering data */ + sslGather gs; /*recvBufLock*/ + + sslBuffer saveBuf; /*xmitBufLock*/ + sslBuffer pendingBuf; /*xmitBufLock*/ + + /* Configuration state for server sockets */ + /* server cert and key for each KEA type */ + sslServerCerts serverCerts[kt_kea_size]; + ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED]; ssl3KeyPair * ephemeralECDHKeyPair; /* for ECDHE-* handshake */ + + /* SSL3 state info. Formerly was a pointer */ + ssl3State ssl3; }; @@ -1074,7 +1076,7 @@ extern int ssl2_StartGatherBytes(sslSocket *ss, sslGather *gs, extern SECStatus ssl_CreateSecurityInfo(sslSocket *ss); extern SECStatus ssl_CopySecurityInfo(sslSocket *ss, sslSocket *os); -extern void ssl_ResetSecurityInfo(sslSecurityInfo *sec); +extern void ssl_ResetSecurityInfo(sslSecurityInfo *sec, PRBool doMemset); extern void ssl_DestroySecurityInfo(sslSecurityInfo *sec); extern sslSocket * ssl_DupSocket(sslSocket *old); @@ -1104,6 +1106,8 @@ extern int ssl3_SendApplicationData(sslSocket *ss, const PRUint8 *in, extern PRBool ssl_FdIsBlocking(PRFileDesc *fd); +extern SECStatus ssl_SetTimeout(PRFileDesc *fd, PRIntervalTime timeout); + extern PRBool ssl_SocketIsBlocking(sslSocket *ss); extern void ssl_SetAlwaysBlock(sslSocket *ss); @@ -1111,33 +1115,57 @@ extern void ssl_SetAlwaysBlock(sslSocket *ss); extern SECStatus ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled); #define SSL_LOCK_READER(ss) if (ss->recvLock) PZ_Lock(ss->recvLock) -#define SSL_UNLOCK_READER(ss) if (ss->recvLock) PZ_Unlock(ss->recvLock) +#define SSL_UNLOCK_READER(ss) if (ss->recvLock) PZ_Unlock(ss->recvLock) #define SSL_LOCK_WRITER(ss) if (ss->sendLock) PZ_Lock(ss->sendLock) -#define SSL_UNLOCK_WRITER(ss) if (ss->sendLock) PZ_Unlock(ss->sendLock) - -#define ssl_Get1stHandshakeLock(ss) PZ_EnterMonitor((ss)->firstHandshakeLock) -#define ssl_Release1stHandshakeLock(ss) PZ_ExitMonitor((ss)->firstHandshakeLock) -#define ssl_Have1stHandshakeLock(ss) PZ_InMonitor( (ss)->firstHandshakeLock) - -#define ssl_GetSSL3HandshakeLock(ss) PZ_EnterMonitor((ss)->ssl3HandshakeLock) -#define ssl_ReleaseSSL3HandshakeLock(ss) PZ_ExitMonitor((ss)->ssl3HandshakeLock) -#define ssl_HaveSSL3HandshakeLock(ss) PZ_InMonitor( (ss)->ssl3HandshakeLock) - -#define ssl_GetSpecReadLock(ss) NSSRWLock_LockRead( (ss)->specLock) -#define ssl_ReleaseSpecReadLock(ss) NSSRWLock_UnlockRead( (ss)->specLock) - -#define ssl_GetSpecWriteLock(ss) NSSRWLock_LockWrite( (ss)->specLock) -#define ssl_ReleaseSpecWriteLock(ss) NSSRWLock_UnlockWrite((ss)->specLock) -#define ssl_HaveSpecWriteLock(ss) NSSRWLock_HaveWriteLock((ss)->specLock) - -#define ssl_GetRecvBufLock(ss) PZ_EnterMonitor((ss)->recvBufLock) -#define ssl_ReleaseRecvBufLock(ss) PZ_ExitMonitor( (ss)->recvBufLock) -#define ssl_HaveRecvBufLock(ss) PZ_InMonitor( (ss)->recvBufLock) - -#define ssl_GetXmitBufLock(ss) PZ_EnterMonitor((ss)->xmitBufLock) -#define ssl_ReleaseXmitBufLock(ss) PZ_ExitMonitor( (ss)->xmitBufLock) -#define ssl_HaveXmitBufLock(ss) PZ_InMonitor( (ss)->xmitBufLock) - +#define SSL_UNLOCK_WRITER(ss) if (ss->sendLock) PZ_Unlock(ss->sendLock) + +#define ssl_Get1stHandshakeLock(ss) \ + { if (!ss->opt.noLocks) PZ_EnterMonitor((ss)->firstHandshakeLock); } +#define ssl_Release1stHandshakeLock(ss) \ + { if (!ss->opt.noLocks) PZ_ExitMonitor((ss)->firstHandshakeLock); } +#define ssl_Have1stHandshakeLock(ss) \ + (PZ_InMonitor((ss)->firstHandshakeLock)) + +#define ssl_GetSSL3HandshakeLock(ss) \ + { if (!ss->opt.noLocks) PZ_EnterMonitor((ss)->ssl3HandshakeLock); } +#define ssl_ReleaseSSL3HandshakeLock(ss) \ + { if (!ss->opt.noLocks) PZ_ExitMonitor((ss)->ssl3HandshakeLock); } +#define ssl_HaveSSL3HandshakeLock(ss) \ + (PZ_InMonitor((ss)->ssl3HandshakeLock)) + +#define ssl_GetSpecReadLock(ss) \ + { if (!ss->opt.noLocks) NSSRWLock_LockRead((ss)->specLock); } +#define ssl_ReleaseSpecReadLock(ss) \ + { if (!ss->opt.noLocks) NSSRWLock_UnlockRead((ss)->specLock); } + +#define ssl_GetSpecWriteLock(ss) \ + { if (!ss->opt.noLocks) NSSRWLock_LockWrite((ss)->specLock); } +#define ssl_ReleaseSpecWriteLock(ss) \ + { if (!ss->opt.noLocks) NSSRWLock_UnlockWrite((ss)->specLock); } +#define ssl_HaveSpecWriteLock(ss) \ + (NSSRWLock_HaveWriteLock((ss)->specLock)) + +#define ssl_GetRecvBufLock(ss) \ + { if (!ss->opt.noLocks) PZ_EnterMonitor((ss)->recvBufLock); } +#define ssl_ReleaseRecvBufLock(ss) \ + { if (!ss->opt.noLocks) PZ_ExitMonitor( (ss)->recvBufLock); } +#define ssl_HaveRecvBufLock(ss) \ + (PZ_InMonitor((ss)->recvBufLock)) + +#define ssl_GetXmitBufLock(ss) \ + { if (!ss->opt.noLocks) PZ_EnterMonitor((ss)->xmitBufLock); } +#define ssl_ReleaseXmitBufLock(ss) \ + { if (!ss->opt.noLocks) PZ_ExitMonitor( (ss)->xmitBufLock); } +#define ssl_HaveXmitBufLock(ss) \ + (PZ_InMonitor((ss)->xmitBufLock)) + + +extern SECStatus ssl3_KeyAndMacDeriveBypass(ssl3CipherSpec * pwSpec, + const unsigned char * cr, const unsigned char * sr, + PRBool isTLS, PRBool isExport); +extern SECStatus ssl3_MasterKeyDeriveBypass( ssl3CipherSpec * pwSpec, + const unsigned char * cr, const unsigned char * sr, + const SECItem * pms, PRBool isTLS, PRBool isRSA); /* These functions are called from secnav, even though they're "private". */ @@ -1220,13 +1248,46 @@ extern SECStatus ssl3_ConstructV2CipherSpecsHack(sslSocket *ss, extern SECStatus ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache); -extern void ssl3_DestroySSL3Info(ssl3State *ssl3); +extern void ssl3_DestroySSL3Info(sslSocket *ss); extern SECStatus ssl3_NegotiateVersion(sslSocket *ss, SSL3ProtocolVersion peerVersion); extern SECStatus ssl_GetPeerInfo(sslSocket *ss); +#ifdef NSS_ENABLE_ECC +/* ECDH functions */ +extern SECStatus ssl3_SendECDHClientKeyExchange(sslSocket * ss, + SECKEYPublicKey * svrPubKey); +extern SECStatus ssl3_HandleECDHServerKeyExchange(sslSocket *ss, + SSL3Opaque *b, PRUint32 length); +extern SECStatus ssl3_HandleECDHClientKeyExchange(sslSocket *ss, + SSL3Opaque *b, PRUint32 length, + SECKEYPublicKey *srvrPubKey, + SECKEYPrivateKey *srvrPrivKey); +extern SECStatus ssl3_SendECDHServerKeyExchange(sslSocket *ss); +#endif + +extern SECStatus ssl3_ComputeCommonKeyHash(PRUint8 * hashBuf, + unsigned int bufLen, SSL3Hashes *hashes, + PRBool bypassPKCS11); +extern SECStatus ssl3_InitPendingCipherSpec(sslSocket *ss, PK11SymKey *pms); +extern SECStatus ssl3_AppendHandshake(sslSocket *ss, const void *void_src, + PRInt32 bytes); +extern SECStatus ssl3_AppendHandshakeHeader(sslSocket *ss, + SSL3HandshakeType t, PRUint32 length); +extern SECStatus ssl3_AppendHandshakeVariable( sslSocket *ss, + const SSL3Opaque *src, PRInt32 bytes, PRInt32 lenSize); +extern SECStatus ssl3_ConsumeHandshake(sslSocket *ss, void *v, PRInt32 bytes, + SSL3Opaque **b, PRUint32 *length); +extern SECStatus ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i, + PRInt32 bytes, SSL3Opaque **b, PRUint32 *length); +extern SECStatus ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key, + SECItem *buf, PRBool isTLS); +extern SECStatus ssl3_VerifySignedHashes(SSL3Hashes *hash, + CERTCertificate *cert, SECItem *buf, PRBool isTLS, + void *pwArg); + /* Construct a new NSPR socket for the app to use */ extern PRFileDesc *ssl_NewPRSocket(sslSocket *ss, PRFileDesc *fd); extern void ssl_FreePRSocket(PRFileDesc *fd); diff --git a/security/nss/lib/ssl/sslinfo.c b/security/nss/lib/ssl/sslinfo.c index 218973a2a..d3a9735f0 100644 --- a/security/nss/lib/ssl/sslinfo.c +++ b/security/nss/lib/ssl/sslinfo.c @@ -60,24 +60,17 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len) memset(&inf, 0, sizeof inf); inf.length = PR_MIN(sizeof inf, len); - if (ss->useSecurity && ss->firstHsDone) { + if (ss->opt.useSecurity && ss->firstHsDone) { sid = ss->sec.ci.sid; inf.protocolVersion = ss->version; inf.authKeyBits = ss->sec.authKeyBits; inf.keaKeyBits = ss->sec.keaKeyBits; if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */ inf.cipherSuite = ss->sec.cipherType | 0xff00; - } else if (ss->ssl3) { /* SSL3 and TLS */ + } else if (ss->ssl3.initialized) { /* SSL3 and TLS */ /* XXX These should come from crSpec */ - inf.cipherSuite = ss->ssl3->hs.cipher_suite; -#if 0 - /* misc */ - inf.isFIPS = (inf.symCipher == ssl_calg_des || inf.symCipher == ssl_calg_3des) - && (inf.macAlgorithm == ssl_mac_sha || inf.macAlgorithm == ssl_hmac_sha) - && (inf.protocolVersion > SSL_LIBRARY_VERSION_3_0 || - inf.cipherSuite >= 0xfef0); -#endif + inf.cipherSuite = ss->ssl3.hs.cipher_suite; } if (sid) { inf.creationTime = sid->creationTime; @@ -85,7 +78,8 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len) inf.expirationTime = sid->expirationTime; if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */ inf.sessionIDLength = SSL2_SESSIONID_BYTES; - memcpy(inf.sessionID, sid->u.ssl2.sessionID, SSL2_SESSIONID_BYTES); + memcpy(inf.sessionID, sid->u.ssl2.sessionID, + SSL2_SESSIONID_BYTES); } else { unsigned int sidLen = sid->u.ssl3.sessionIDLength; sidLen = PR_MIN(sidLen, sizeof inf.sessionID); @@ -100,8 +94,6 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len) return SECSuccess; } -#define kt_kea kt_fortezza -#define calg_sj calg_fortezza #define CS(x) x, #x #define CK(x) x | 0xff00, #x @@ -139,34 +131,31 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len) static const SSLCipherSuiteInfo suiteInfo[] = { /* <------ Cipher suite --------------------> <auth> <KEA> <bulk cipher> <MAC> <FIPS> */ -{0,CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_DHE, C_AES, B_256, M_SHA, 0, 0, 0, }, -{0,CS(TLS_DHE_DSS_WITH_AES_256_CBC_SHA), S_DSA, K_DHE, C_AES, B_256, M_SHA, 0, 0, 0, }, -{0,CS(TLS_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_RSA, C_AES, B_256, M_SHA, 0, 0, 0, }, +{0,CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_DHE, C_AES, B_256, M_SHA, 1, 0, 0, }, +{0,CS(TLS_DHE_DSS_WITH_AES_256_CBC_SHA), S_DSA, K_DHE, C_AES, B_256, M_SHA, 1, 0, 0, }, +{0,CS(TLS_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_RSA, C_AES, B_256, M_SHA, 1, 0, 0, }, -{0,CS(SSL_FORTEZZA_DMS_WITH_RC4_128_SHA), S_KEA, K_KEA, C_RC4, B_128, M_SHA, 0, 0, 0, }, {0,CS(TLS_DHE_DSS_WITH_RC4_128_SHA), S_DSA, K_DHE, C_RC4, B_128, M_SHA, 0, 0, 0, }, -{0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_DHE, C_AES, B_128, M_SHA, 0, 0, 0, }, -{0,CS(TLS_DHE_DSS_WITH_AES_128_CBC_SHA), S_DSA, K_DHE, C_AES, B_128, M_SHA, 0, 0, 0, }, +{0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0, }, +{0,CS(TLS_DHE_DSS_WITH_AES_128_CBC_SHA), S_DSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0, }, {0,CS(SSL_RSA_WITH_RC4_128_MD5), S_RSA, K_RSA, C_RC4, B_128, M_MD5, 0, 0, 0, }, {0,CS(SSL_RSA_WITH_RC4_128_SHA), S_RSA, K_RSA, C_RC4, B_128, M_SHA, 0, 0, 0, }, -{0,CS(TLS_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_RSA, C_AES, B_128, M_SHA, 0, 0, 0, }, +{0,CS(TLS_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_RSA, C_AES, B_128, M_SHA, 1, 0, 0, }, -{0,CS(SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_DHE, C_3DES,B_3DES,M_SHA, 0, 0, 0, }, -{0,CS(SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA), S_DSA, K_DHE, C_3DES,B_3DES,M_SHA, 0, 0, 0, }, +{0,CS(SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_DHE, C_3DES,B_3DES,M_SHA, 1, 0, 0, }, +{0,CS(SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA), S_DSA, K_DHE, C_3DES,B_3DES,M_SHA, 1, 0, 0, }, {0,CS(SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA), S_RSA, K_RSA, C_3DES,B_3DES,M_SHA, 1, 0, 1, }, {0,CS(SSL_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_RSA, C_3DES,B_3DES,M_SHA, 1, 0, 0, }, -{0,CS(SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA),S_KEA, K_KEA, C_SJ, B_SJ, M_SHA, 1, 0, 0, }, {0,CS(SSL_DHE_RSA_WITH_DES_CBC_SHA), S_RSA, K_DHE, C_DES, B_DES, M_SHA, 0, 0, 0, }, {0,CS(SSL_DHE_DSS_WITH_DES_CBC_SHA), S_DSA, K_DHE, C_DES, B_DES, M_SHA, 0, 0, 0, }, -{0,CS(SSL_RSA_FIPS_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, 1, 0, 1, }, -{0,CS(SSL_RSA_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, 1, 0, 0, }, +{0,CS(SSL_RSA_FIPS_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 0, 1, }, +{0,CS(SSL_RSA_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 0, 0, }, {0,CS(TLS_RSA_EXPORT1024_WITH_RC4_56_SHA), S_RSA, K_RSA, C_RC4, B_56, M_SHA, 0, 1, 0, }, -{0,CS(TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, 1, 1, 0, }, +{0,CS(TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 1, 0, }, {0,CS(SSL_RSA_EXPORT_WITH_RC4_40_MD5), S_RSA, K_RSA, C_RC4, B_40, M_MD5, 0, 1, 0, }, {0,CS(SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5), S_RSA, K_RSA, C_RC2, B_40, M_MD5, 0, 1, 0, }, -{0,CS(SSL_FORTEZZA_DMS_WITH_NULL_SHA), S_KEA, K_KEA, C_NULL,B_0, M_SHA, 0, 1, 0, }, {0,CS(SSL_RSA_WITH_NULL_SHA), S_RSA, K_RSA, C_NULL,B_0, M_SHA, 0, 1, 0, }, {0,CS(SSL_RSA_WITH_NULL_MD5), S_RSA, K_RSA, C_NULL,B_0, M_MD5, 0, 1, 0, }, @@ -175,20 +164,20 @@ static const SSLCipherSuiteInfo suiteInfo[] = { {0,CS(TLS_ECDH_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0, }, {0,CS(TLS_ECDH_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDH, C_RC4, B_128, M_SHA, 0, 0, 0, }, {0,CS(TLS_ECDH_ECDSA_WITH_DES_CBC_SHA), S_ECDSA, K_ECDH, C_DES, B_DES, M_SHA, 0, 0, 0, }, -{0,CS(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDH, C_3DES, B_3DES, M_SHA, 0, 0, 0, }, -{0,CS(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_128, M_SHA, 0, 0, 0, }, -{0,CS(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_256, M_SHA, 0, 0, 0, }, +{0,CS(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDH, C_3DES, B_3DES, M_SHA, 1, 0, 0, }, +{0,CS(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_128, M_SHA, 1, 0, 0, }, +{0,CS(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_256, M_SHA, 1, 0, 0, }, {0,CS(TLS_ECDH_RSA_WITH_NULL_SHA), S_RSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0, }, {0,CS(TLS_ECDH_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDH, C_RC4, B_128, M_SHA, 0, 0, 0, }, {0,CS(TLS_ECDH_RSA_WITH_DES_CBC_SHA), S_RSA, K_ECDH, C_DES, B_DES, M_SHA, 0, 0, 0, }, -{0,CS(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDH, C_3DES, B_3DES, M_SHA, 0, 0, 0, }, -{0,CS(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDH, C_AES, B_128, M_SHA, 0, 0, 0, }, -{0,CS(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDH, C_AES, B_256, M_SHA, 0, 0, 0, }, +{0,CS(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDH, C_3DES, B_3DES, M_SHA, 1, 0, 0, }, +{0,CS(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDH, C_AES, B_128, M_SHA, 1, 0, 0, }, +{0,CS(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDH, C_AES, B_256, M_SHA, 1, 0, 0, }, -{0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA, 0, 0, 0, }, +{0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA, 1, 0, 0, }, -{0,CS(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_128, M_SHA, 0, 0, 0, }, +{0,CS(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_128, M_SHA, 1, 0, 0, }, #endif /* NSS_ENABLE_ECC */ /* SSL 2 table */ diff --git a/security/nss/lib/ssl/sslnonce.c b/security/nss/lib/ssl/sslnonce.c index 1a02666e5..e2dbcf0a5 100644 --- a/security/nss/lib/ssl/sslnonce.c +++ b/security/nss/lib/ssl/sslnonce.c @@ -193,7 +193,7 @@ ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID, PORT_Strcmp(sid->peerID, peerID) == 0)) && /* is cacheable */ (sid->version < SSL_LIBRARY_VERSION_3_0 || - sid->u.ssl3.resumable) && + sid->u.ssl3.keys.resumable) && /* server hostname matches. */ (sid->urlSvrName != NULL) && ((0 == PORT_Strcmp(urlSvrName, sid->urlSvrName)) || diff --git a/security/nss/lib/ssl/sslproto.h b/security/nss/lib/ssl/sslproto.h index fa0639605..e7a998126 100644 --- a/security/nss/lib/ssl/sslproto.h +++ b/security/nss/lib/ssl/sslproto.h @@ -139,9 +139,9 @@ #define SSL_DH_ANON_WITH_DES_CBC_SHA 0x001a #define SSL_DH_ANON_WITH_3DES_EDE_CBC_SHA 0x001b -#define SSL_FORTEZZA_DMS_WITH_NULL_SHA 0x001c -#define SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA 0x001d -#define SSL_FORTEZZA_DMS_WITH_RC4_128_SHA 0x001e +#define SSL_FORTEZZA_DMS_WITH_NULL_SHA 0x001c /* deprecated */ +#define SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA 0x001d /* deprecated */ +#define SSL_FORTEZZA_DMS_WITH_RC4_128_SHA 0x001e /* deprecated */ /* New TLS cipher suites */ #define TLS_RSA_WITH_AES_128_CBC_SHA 0x002F diff --git a/security/nss/lib/ssl/sslsecur.c b/security/nss/lib/ssl/sslsecur.c index 404f9a7dc..a30b062df 100644 --- a/security/nss/lib/ssl/sslsecur.c +++ b/security/nss/lib/ssl/sslsecur.c @@ -112,9 +112,9 @@ ssl_Do1stHandshake(sslSocket *ss) int loopCount = 0; do { - PORT_Assert( ssl_Have1stHandshakeLock(ss) ); - PORT_Assert( !ssl_HaveRecvBufLock(ss) ); - PORT_Assert( !ssl_HaveXmitBufLock(ss) ); + PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); + PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss)); + PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss)); if (ss->handshake == 0) { /* Previous handshake finished. Switch to next one */ @@ -153,8 +153,8 @@ ssl_Do1stHandshake(sslSocket *ss) */ } while (rv != SECFailure); /* was (rv >= 0); XXX_1 */ - PORT_Assert( !ssl_HaveRecvBufLock(ss) ); - PORT_Assert( !ssl_HaveXmitBufLock(ss) ); + PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss)); + PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss)); if (rv == SECWouldBlock) { PORT_SetError(PR_WOULD_BLOCK_ERROR); @@ -202,7 +202,7 @@ SSL_ResetHandshake(PRFileDesc *s, PRBool asServer) } /* Don't waste my time */ - if (!ss->useSecurity) + if (!ss->opt.useSecurity) return SECSuccess; SSL_LOCK_READER(ss); @@ -231,7 +231,7 @@ SSL_ResetHandshake(PRFileDesc *s, PRBool asServer) ** Blow away old security state and get a fresh setup. */ ssl_GetXmitBufLock(ss); - ssl_ResetSecurityInfo(&ss->sec); + ssl_ResetSecurityInfo(&ss->sec, PR_TRUE); status = ssl_CreateSecurityInfo(ss); ssl_ReleaseXmitBufLock(ss); @@ -264,7 +264,7 @@ SSL_ReHandshake(PRFileDesc *fd, PRBool flushCache) return SECFailure; } - if (!ss->useSecurity) + if (!ss->opt.useSecurity) return SECSuccess; ssl_Get1stHandshakeLock(ss); @@ -284,6 +284,19 @@ SSL_ReHandshake(PRFileDesc *fd, PRBool flushCache) return rv; } +/* +** Same as above, but with an I/O timeout. + */ +SSL_IMPORT SECStatus SSL_ReHandshakeWithTimeout(PRFileDesc *fd, + PRBool flushCache, + PRIntervalTime timeout) +{ + if (SECSuccess != ssl_SetTimeout(fd, timeout)) { + return SECFailure; + } + return SSL_ReHandshake(fd, flushCache); +} + SECStatus SSL_RedoHandshake(PRFileDesc *fd) { @@ -306,7 +319,7 @@ SSL_HandshakeCallback(PRFileDesc *fd, SSLHandshakeCallback cb, return SECFailure; } - if (!ss->useSecurity) { + if (!ss->opt.useSecurity) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } @@ -347,7 +360,7 @@ SSL_ForceHandshake(PRFileDesc *fd) } /* Don't waste my time */ - if (!ss->useSecurity) + if (!ss->opt.useSecurity) return SECSuccess; ssl_Get1stHandshakeLock(ss); @@ -378,6 +391,19 @@ SSL_ForceHandshake(PRFileDesc *fd) return rv; } +/* + ** Same as above, but with an I/O timeout. + */ +SSL_IMPORT SECStatus SSL_ForceHandshakeWithTimeout(PRFileDesc *fd, + PRIntervalTime timeout) +{ + if (SECSuccess != ssl_SetTimeout(fd, timeout)) { + return SECFailure; + } + return SSL_ForceHandshake(fd); +} + + /************************************************************************/ /* @@ -388,17 +414,20 @@ SSL_ForceHandshake(PRFileDesc *fd) SECStatus sslBuffer_Grow(sslBuffer *b, unsigned int newLen) { + newLen = PR_MAX(newLen, MAX_FRAGMENT_LENGTH + 2048); if (newLen > b->space) { + unsigned char *newBuf; if (b->buf) { - b->buf = (unsigned char *) PORT_Realloc(b->buf, newLen); + newBuf = (unsigned char *) PORT_Realloc(b->buf, newLen); } else { - b->buf = (unsigned char *) PORT_Alloc(newLen); + newBuf = (unsigned char *) PORT_Alloc(newLen); } - if (!b->buf) { + if (!newBuf) { return SECFailure; } SSL_TRC(10, ("%d: SSL: grow buffer from %d to %d", SSL_GETPID(), b->space, newLen)); + b->buf = newBuf; b->space = newLen; } return SECSuccess; @@ -417,7 +446,7 @@ ssl_SaveWriteData(sslSocket *ss, sslBuffer *buf, const void *data, unsigned int newlen; SECStatus rv; - PORT_Assert( ssl_HaveXmitBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); newlen = buf->len + len; if (newlen > buf->space) { rv = sslBuffer_Grow(buf, newlen); @@ -444,7 +473,7 @@ ssl_SendSavedWriteData(sslSocket *ss, sslBuffer *buf, sslSendFunc send) int rv = 0; int len = buf->len; - PORT_Assert( ssl_HaveXmitBufLock(ss) ); + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); if (len != 0) { SSL_TRC(5, ("%d: SSL[%d]: sending %d bytes of saved data", SSL_GETPID(), ss->fd, len)); @@ -574,12 +603,7 @@ ssl_FindCertKEAType(CERTCertificate * cert) case SEC_OID_PKCS1_RSA_ENCRYPTION: keaType = kt_rsa; break; - case SEC_OID_MISSI_KEA_DSS_OLD: - case SEC_OID_MISSI_KEA_DSS: - case SEC_OID_MISSI_DSS_OLD: - case SEC_OID_MISSI_DSS: - keaType = kt_fortezza; - break; + case SEC_OID_X942_DIFFIE_HELMAN_KEY: keaType = kt_dh; break; @@ -667,19 +691,47 @@ SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert, } /* load the private key */ - if (sc->serverKey != NULL) { - SECKEY_DestroyPrivateKey(sc->serverKey); - sc->serverKey = NULL; + if (sc->serverKeyPair != NULL) { + ssl3_FreeKeyPair(sc->serverKeyPair); + sc->serverKeyPair = NULL; } if (key) { - sc->serverKey = SECKEY_CopyPrivateKey(key); - if (sc->serverKey == NULL) + SECKEYPrivateKey * keyCopy = NULL; + CK_MECHANISM_TYPE keyMech = CKM_INVALID_MECHANISM; + + if (key->pkcs11Slot) { + PK11SlotInfo * bestSlot; + bestSlot = PK11_ReferenceSlot(key->pkcs11Slot); + if (bestSlot) { + keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); + PK11_FreeSlot(bestSlot); + } + } + if (keyCopy == NULL) + keyMech = PK11_MapSignKeyType(key->keyType); + if (keyMech != CKM_INVALID_MECHANISM) { + PK11SlotInfo * bestSlot; + /* XXX Maybe should be bestSlotMultiple? */ + bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */); + if (bestSlot) { + keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); + PK11_FreeSlot(bestSlot); + } + } + if (keyCopy == NULL) + keyCopy = SECKEY_CopyPrivateKey(key); + if (keyCopy == NULL) goto loser; - SECKEY_CacheStaticFlags(sc->serverKey); + SECKEY_CacheStaticFlags(keyCopy); + sc->serverKeyPair = ssl3_NewKeyPair(keyCopy, NULL); + if (sc->serverKeyPair == NULL) { + SECKEY_DestroyPrivateKey(keyCopy); + goto loser; + } } if (kea == kt_rsa && cert && sc->serverKeyBits > 512) { - if (ss->noStepDown) { + if (ss->opt.noStepDown) { /* disable all export ciphersuites */ } else { rv = ssl3_CreateRSAStepDownKeys(ss); @@ -704,9 +756,9 @@ loser: CERT_DestroyCertificateList(sc->serverCertChain); sc->serverCertChain = NULL; } - if (sc->serverKey != NULL) { - SECKEY_DestroyPrivateKey(sc->serverKey); - sc->serverKey = NULL; + if (sc->serverKeyPair != NULL) { + ssl3_FreeKeyPair(sc->serverKeyPair); + sc->serverKeyPair = NULL; } return SECFailure; } @@ -791,7 +843,7 @@ loser: ** Caller holds any relevant locks. */ void -ssl_ResetSecurityInfo(sslSecurityInfo *sec) +ssl_ResetSecurityInfo(sslSecurityInfo *sec, PRBool doMemset) { /* Destroy MAC */ if (sec->hash && sec->hashcx) { @@ -833,7 +885,10 @@ ssl_ResetSecurityInfo(sslSecurityInfo *sec) ssl_FreeSID(sec->ci.sid); } PORT_ZFree(sec->ci.sendBuf.buf, sec->ci.sendBuf.space); - memset(&sec->ci, 0, sizeof sec->ci); + if (doMemset) { + memset(&sec->ci, 0, sizeof sec->ci); + } + } /* @@ -844,7 +899,7 @@ ssl_ResetSecurityInfo(sslSecurityInfo *sec) void ssl_DestroySecurityInfo(sslSecurityInfo *sec) { - ssl_ResetSecurityInfo(sec); + ssl_ResetSecurityInfo(sec, PR_FALSE); PORT_ZFree(sec->writeBuf.buf, sec->writeBuf.space); sec->writeBuf.buf = 0; @@ -860,7 +915,7 @@ ssl_SecureConnect(sslSocket *ss, const PRNetAddr *sa) PRFileDesc *osfd = ss->fd->lower; int rv; - if ( ss->handshakeAsServer ) { + if ( ss->opt.handshakeAsServer ) { ss->securityHandshake = ssl2_BeginServerHandshake; ss->handshaking = sslHandshakingAsServer; } else { @@ -895,7 +950,7 @@ ssl_SecureClose(sslSocket *ss) ss->firstHsDone && !(ss->shutdownHow & ssl_SHUTDOWN_SEND) && !ss->recvdCloseNotify && - (ss->ssl3 != NULL)) { + ss->ssl3.initialized) { /* We don't want the final alert to be Nagle delayed. */ if (!ss->delayDisabled) { @@ -927,7 +982,7 @@ ssl_SecureShutdown(sslSocket *ss, int nsprHow) (ss->version >= SSL_LIBRARY_VERSION_3_0) && ss->firstHsDone && !ss->recvdCloseNotify && - (ss->ssl3 != NULL)) { + ss->ssl3.initialized) { (void) SSL3_SendAlert(ss, alert_warning, close_notify); } @@ -959,7 +1014,7 @@ ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags) return PR_FAILURE; } - if (!ssl_SocketIsBlocking(ss) && !ss->fdx) { + if (!ssl_SocketIsBlocking(ss) && !ss->opt.fdx) { ssl_GetXmitBufLock(ss); if (ss->pendingBuf.len != 0) { rv = ssl_SendSavedWriteData(ss, &ss->pendingBuf, ssl_DefSend); @@ -1135,7 +1190,7 @@ SSL_DataPending(PRFileDesc *fd) ss = ssl_FindSocket(fd); - if (ss && ss->useSecurity) { + if (ss && ss->opt.useSecurity) { ssl_Get1stHandshakeLock(ss); ssl_GetSSL3HandshakeLock(ss); @@ -1183,7 +1238,7 @@ SSL_GetSessionID(PRFileDesc *fd) ssl_Get1stHandshakeLock(ss); ssl_GetSSL3HandshakeLock(ss); - if (ss->useSecurity && ss->firstHsDone && ss->sec.ci.sid) { + if (ss->opt.useSecurity && ss->firstHsDone && ss->sec.ci.sid) { item = (SECItem *)PORT_Alloc(sizeof(SECItem)); if (item) { sslSessionID * sid = ss->sec.ci.sid; diff --git a/security/nss/lib/ssl/sslsnce.c b/security/nss/lib/ssl/sslsnce.c index 345104f1f..877a5a995 100644 --- a/security/nss/lib/ssl/sslsnce.c +++ b/security/nss/lib/ssl/sslsnce.c @@ -146,17 +146,15 @@ struct sidCacheEntryStr { /* 2 */ ssl3CipherSuite cipherSuite; /* 2 */ PRUint16 compression; /* SSL3CompressionMethod */ -/*122 */ ssl3SidKeys keys; /* keys and ivs, wrapped as needed. */ -/* 1 */ PRUint8 hasFortezza; -/* 1 */ PRUint8 resumable; +/*100 */ ssl3SidKeys keys; /* keys and ivs, wrapped as needed. */ /* 4 */ PRUint32 masterWrapMech; /* 4 */ SSL3KEAType exchKeyType; /* 4 */ PRInt32 certIndex; -/*140 */} ssl3; -#if defined(LINUX) +/*116 */} ssl3; +#if defined(LINUX) /* XXX Why only on Linux ? */ struct { - PRUint8 filler[144]; + PRUint8 filler[144]; /* XXX why this number ? */ } forceSize; #endif } u; @@ -441,8 +439,6 @@ ConvertFromSID(sidCacheEntry *to, sslSessionID *from) to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite; to->u.ssl3.compression = (uint16)from->u.ssl3.compression; - to->u.ssl3.resumable = from->u.ssl3.resumable; - to->u.ssl3.hasFortezza = from->u.ssl3.hasFortezza; to->u.ssl3.keys = from->u.ssl3.keys; to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech; to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType; @@ -517,8 +513,6 @@ ConvertToSID(sidCacheEntry *from, certCacheEntry *pcce, to->u.ssl3.sessionIDLength = from->sessionIDLength; to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite; to->u.ssl3.compression = (SSL3CompressionMethod)from->u.ssl3.compression; - to->u.ssl3.resumable = from->u.ssl3.resumable; - to->u.ssl3.hasFortezza = from->u.ssl3.hasFortezza; to->u.ssl3.keys = from->u.ssl3.keys; to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech; to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType; @@ -530,7 +524,7 @@ ConvertToSID(sidCacheEntry *from, certCacheEntry *pcce, */ to->u.ssl3.clientWriteKey = NULL; to->u.ssl3.serverWriteKey = NULL; - to->u.ssl3.tek = NULL; + to->urlSvrName = NULL; to->u.ssl3.masterModuleID = (SECMODModuleID)-1; /* invalid value */ @@ -544,8 +538,6 @@ ConvertToSID(sidCacheEntry *from, certCacheEntry *pcce, to->u.ssl3.clAuthSeries = 0; to->u.ssl3.clAuthValid = PR_FALSE; - to->u.ssl3.clientWriteSaveLen = 0; - if (from->u.ssl3.certIndex != -1 && pcce) { SECItem derCert; @@ -929,6 +921,11 @@ InitCache(cacheDesc *cache, int maxCacheEntries, PRUint32 ssl2_timeout, int locks_to_initialize = 0; PRUint32 init_time; + if ( (!cache) || (maxCacheEntries < 0) || (!directory) ) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (cache->cacheMem) { /* Already done */ return SECSuccess; diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c index 9803eec96..6344c99c5 100644 --- a/security/nss/lib/ssl/sslsock.c +++ b/security/nss/lib/ssl/sslsock.c @@ -71,8 +71,6 @@ static cipherPolicy ssl_ciphers[] = { /* Export France */ { SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, SSL_ALLOWED, SSL_ALLOWED }, { SSL_EN_DES_64_CBC_WITH_MD5, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, { SSL_EN_DES_192_EDE3_CBC_WITH_MD5, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, - { SSL_FORTEZZA_DMS_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, { SSL_RSA_WITH_RC4_128_MD5, SSL_RESTRICTED, SSL_NOT_ALLOWED }, { SSL_RSA_WITH_RC4_128_SHA, SSL_RESTRICTED, SSL_NOT_ALLOWED }, { SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, @@ -81,7 +79,6 @@ static cipherPolicy ssl_ciphers[] = { /* Export France */ { SSL_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, { SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_ALLOWED, SSL_ALLOWED }, { SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_ALLOWED, SSL_ALLOWED }, - { SSL_FORTEZZA_DMS_WITH_NULL_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, { SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, { SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, { SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, SSL_NOT_ALLOWED }, @@ -164,6 +161,8 @@ static sslOptions ssl_defaults = { PR_TRUE, /* v2CompatibleHello */ PR_TRUE, /* detectRollBack */ PR_FALSE, /* noStepDown */ + PR_FALSE, /* bypassPKCS11 */ + PR_FALSE, /* noLocks */ }; sslSessionIDLookupFunc ssl_sid_lookup; @@ -173,13 +172,17 @@ sslSessionIDUncacheFunc ssl_sid_uncache; static PRBool ssl_inited = PR_FALSE; static PRDescIdentity ssl_layer_id; +PRBool locksEverDisabled; /* implicitly PR_FALSE */ +PRBool ssl_force_locks; /* implicitly PR_FALSE */ int ssl_lock_readers = 1; /* default true. */ char ssl_debug; char ssl_trace; - +char lockStatus[] = "Locks are ENABLED. "; +#define LOCKSTATUS_OFFSET 10 /* offset of ENABLED */ /* forward declarations. */ -static sslSocket *ssl_NewSocket(void); +static sslSocket *ssl_NewSocket(PRBool makeLocks); +static SECStatus ssl_MakeLocks(sslSocket *ss); static PRStatus ssl_PushIOLayer(sslSocket *ns, PRFileDesc *stack, PRDescIdentity id); @@ -230,22 +233,10 @@ ssl_DupSocket(sslSocket *os) sslSocket *ss; SECStatus rv; - ss = ssl_NewSocket(); + ss = ssl_NewSocket((PRBool)(!os->opt.noLocks)); if (ss) { - ss->useSocks = PR_FALSE; - ss->useSecurity = os->useSecurity; - ss->requestCertificate = os->requestCertificate; - ss->requireCertificate = os->requireCertificate; - ss->handshakeAsClient = os->handshakeAsClient; - ss->handshakeAsServer = os->handshakeAsServer; - ss->enableSSL2 = os->enableSSL2; - ss->enableSSL3 = os->enableSSL3; - ss->enableTLS = os->enableTLS; - ss->noCache = os->noCache; - ss->fdx = os->fdx; - ss->v2CompatibleHello = os->v2CompatibleHello; - ss->detectRollBack = os->detectRollBack; - ss->noStepDown = os->noStepDown; + ss->opt = os->opt; + ss->opt.useSocks = PR_FALSE; ss->peerID = !os->peerID ? NULL : PORT_Strdup(os->peerID); ss->url = !os->url ? NULL : PORT_Strdup(os->url); @@ -274,7 +265,7 @@ ssl_DupSocket(sslSocket *os) ss->sizeCipherSpecs = 0; ss->preferredCipher = NULL; } - if (ss->useSecurity) { + if (ss->opt.useSecurity) { /* This int should be SSLKEAType, but CC on Irix complains, * during the for loop. */ @@ -292,9 +283,9 @@ ssl_DupSocket(sslSocket *os) sc->serverCert = NULL; sc->serverCertChain = NULL; } - sc->serverKey = oc->serverKey ? - SECKEY_CopyPrivateKey(oc->serverKey) : NULL; - if (oc->serverKey && !sc->serverKey) + sc->serverKeyPair = oc->serverKeyPair ? + ssl3_GetKeyPairRef(oc->serverKeyPair) : NULL; + if (oc->serverKeyPair && !sc->serverKeyPair) goto loser; sc->serverKeyBits = oc->serverKeyBits; } @@ -331,7 +322,6 @@ loser: static void ssl_DestroyLocks(sslSocket *ss) { - /* Destroy locks. */ if (ss->firstHandshakeLock) { PZ_DestroyMonitor(ss->firstHandshakeLock); @@ -376,7 +366,7 @@ ssl_DestroySocketContents(sslSocket *ss) /* Free up socket */ ssl_DestroySecurityInfo(&ss->sec); - ssl3_DestroySSL3Info(ss->ssl3); + ssl3_DestroySSL3Info(ss); PORT_Free(ss->saveBuf.buf); PORT_Free(ss->pendingBuf.buf); @@ -399,8 +389,8 @@ ssl_DestroySocketContents(sslSocket *ss) CERT_DestroyCertificate(sc->serverCert); if (sc->serverCertChain != NULL) CERT_DestroyCertificateList(sc->serverCertChain); - if (sc->serverKey != NULL) - SECKEY_DestroyPrivateKey(sc->serverKey); + if (sc->serverKeyPair != NULL) + ssl3_FreeKeyPair(sc->serverKeyPair); } if (ss->stepDownKeyPair) { ssl3_FreeKeyPair(ss->stepDownKeyPair); @@ -479,7 +469,7 @@ ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled) static void ssl_ChooseOps(sslSocket *ss) { - ss->ops = ss->useSecurity ? &ssl_secure_ops : &ssl_default_ops; + ss->ops = ss->opt.useSecurity ? &ssl_secure_ops : &ssl_default_ops; } /* Called from SSL_Enable (immediately below) */ @@ -503,18 +493,20 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) { sslSocket *ss = ssl_FindSocket(fd); SECStatus rv = SECSuccess; + PRBool holdingLocks; if (!ss) { SSL_DBG(("%d: SSL[%d]: bad socket in Enable", SSL_GETPID(), fd)); return SECFailure; } + holdingLocks = (!ss->opt.noLocks); ssl_Get1stHandshakeLock(ss); ssl_GetSSL3HandshakeLock(ss); switch (which) { case SSL_SOCKS: - ss->useSocks = PR_FALSE; + ss->opt.useSocks = PR_FALSE; rv = PrepareSocket(ss); if (on) { PORT_SetError(SEC_ERROR_INVALID_ARGS); @@ -523,38 +515,38 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) break; case SSL_SECURITY: - ss->useSecurity = on; + ss->opt.useSecurity = on; rv = PrepareSocket(ss); break; case SSL_REQUEST_CERTIFICATE: - ss->requestCertificate = on; + ss->opt.requestCertificate = on; break; case SSL_REQUIRE_CERTIFICATE: - ss->requireCertificate = on; + ss->opt.requireCertificate = on; break; case SSL_HANDSHAKE_AS_CLIENT: - if ( ss->handshakeAsServer && on ) { + if ( ss->opt.handshakeAsServer && on ) { PORT_SetError(SEC_ERROR_INVALID_ARGS); rv = SECFailure; break; } - ss->handshakeAsClient = on; + ss->opt.handshakeAsClient = on; break; case SSL_HANDSHAKE_AS_SERVER: - if ( ss->handshakeAsClient && on ) { + if ( ss->opt.handshakeAsClient && on ) { PORT_SetError(SEC_ERROR_INVALID_ARGS); rv = SECFailure; break; } - ss->handshakeAsServer = on; + ss->opt.handshakeAsServer = on; break; case SSL_ENABLE_TLS: - ss->enableTLS = on; + ss->opt.enableTLS = on; ss->preferredCipher = NULL; if (ss->cipherSpecs) { PORT_Free(ss->cipherSpecs); @@ -564,7 +556,7 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) break; case SSL_ENABLE_SSL3: - ss->enableSSL3 = on; + ss->opt.enableSSL3 = on; ss->preferredCipher = NULL; if (ss->cipherSpecs) { PORT_Free(ss->cipherSpecs); @@ -574,9 +566,9 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) break; case SSL_ENABLE_SSL2: - ss->enableSSL2 = on; + ss->opt.enableSSL2 = on; if (on) { - ss->v2CompatibleHello = on; + ss->opt.v2CompatibleHello = on; } ss->preferredCipher = NULL; if (ss->cipherSpecs) { @@ -587,37 +579,76 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) break; case SSL_NO_CACHE: - ss->noCache = on; + ss->opt.noCache = on; break; case SSL_ENABLE_FDX: - ss->fdx = on; + if (on && ss->opt.noLocks) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + rv = SECFailure; + } + ss->opt.fdx = on; break; case SSL_V2_COMPATIBLE_HELLO: - ss->v2CompatibleHello = on; + ss->opt.v2CompatibleHello = on; if (!on) { - ss->enableSSL2 = on; + ss->opt.enableSSL2 = on; } break; case SSL_ROLLBACK_DETECTION: - ss->detectRollBack = on; + ss->opt.detectRollBack = on; break; case SSL_NO_STEP_DOWN: - ss->noStepDown = on; + ss->opt.noStepDown = on; if (on) SSL_DisableExportCipherSuites(fd); break; + case SSL_BYPASS_PKCS11: + if (ss->handshakeBegun) { + PORT_SetError(PR_INVALID_STATE_ERROR); + rv = SECFailure; + } else { + ss->opt.bypassPKCS11 = on; + } + break; + + case SSL_NO_LOCKS: + if (on && ss->opt.fdx) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + rv = SECFailure; + } + if (on && ssl_force_locks) + on = PR_FALSE; /* silent override */ + ss->opt.noLocks = on; + if (on) { + locksEverDisabled = PR_TRUE; + strcpy(lockStatus + LOCKSTATUS_OFFSET, "DISABLED."); + } else if (!holdingLocks) { + rv = ssl_MakeLocks(ss); + if (rv != SECSuccess) { + ss->opt.noLocks = PR_TRUE; + } + } + break; + default: PORT_SetError(SEC_ERROR_INVALID_ARGS); rv = SECFailure; } - ssl_ReleaseSSL3HandshakeLock(ss); - ssl_Release1stHandshakeLock(ss); + /* We can't use the macros for releasing the locks here, + * because ss->opt.noLocks might have changed just above. + * We must release these locks (monitors) here, if we aquired them above, + * regardless of the current value of ss->opt.noLocks. + */ + if (holdingLocks) { + PZ_ExitMonitor((ss)->ssl3HandshakeLock); + PZ_ExitMonitor((ss)->firstHandshakeLock); + } return rv; } @@ -644,19 +675,21 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn) switch (which) { case SSL_SOCKS: on = PR_FALSE; break; - case SSL_SECURITY: on = ss->useSecurity; break; - case SSL_REQUEST_CERTIFICATE: on = ss->requestCertificate; break; - case SSL_REQUIRE_CERTIFICATE: on = ss->requireCertificate; break; - case SSL_HANDSHAKE_AS_CLIENT: on = ss->handshakeAsClient; break; - case SSL_HANDSHAKE_AS_SERVER: on = ss->handshakeAsServer; break; - case SSL_ENABLE_TLS: on = ss->enableTLS; break; - case SSL_ENABLE_SSL3: on = ss->enableSSL3; break; - case SSL_ENABLE_SSL2: on = ss->enableSSL2; break; - case SSL_NO_CACHE: on = ss->noCache; break; - case SSL_ENABLE_FDX: on = ss->fdx; break; - case SSL_V2_COMPATIBLE_HELLO: on = ss->v2CompatibleHello; break; - case SSL_ROLLBACK_DETECTION: on = ss->detectRollBack; break; - case SSL_NO_STEP_DOWN: on = ss->noStepDown; break; + case SSL_SECURITY: on = ss->opt.useSecurity; break; + case SSL_REQUEST_CERTIFICATE: on = ss->opt.requestCertificate; break; + case SSL_REQUIRE_CERTIFICATE: on = ss->opt.requireCertificate; break; + case SSL_HANDSHAKE_AS_CLIENT: on = ss->opt.handshakeAsClient; break; + case SSL_HANDSHAKE_AS_SERVER: on = ss->opt.handshakeAsServer; break; + case SSL_ENABLE_TLS: on = ss->opt.enableTLS; break; + case SSL_ENABLE_SSL3: on = ss->opt.enableSSL3; break; + case SSL_ENABLE_SSL2: on = ss->opt.enableSSL2; break; + case SSL_NO_CACHE: on = ss->opt.noCache; break; + case SSL_ENABLE_FDX: on = ss->opt.fdx; break; + case SSL_V2_COMPATIBLE_HELLO: on = ss->opt.v2CompatibleHello; break; + case SSL_ROLLBACK_DETECTION: on = ss->opt.detectRollBack; break; + case SSL_NO_STEP_DOWN: on = ss->opt.noStepDown; break; + case SSL_BYPASS_PKCS11: on = ss->opt.bypassPKCS11; break; + case SSL_NO_LOCKS: on = ss->opt.noLocks; break; default: PORT_SetError(SEC_ERROR_INVALID_ARGS); @@ -696,6 +729,8 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn) case SSL_V2_COMPATIBLE_HELLO: on = ssl_defaults.v2CompatibleHello; break; case SSL_ROLLBACK_DETECTION: on = ssl_defaults.detectRollBack; break; case SSL_NO_STEP_DOWN: on = ssl_defaults.noStepDown; break; + case SSL_BYPASS_PKCS11: on = ssl_defaults.bypassPKCS11; break; + case SSL_NO_LOCKS: on = ssl_defaults.noLocks; break; default: PORT_SetError(SEC_ERROR_INVALID_ARGS); @@ -773,6 +808,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on) break; case SSL_ENABLE_FDX: + if (on && ssl_defaults.noLocks) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } ssl_defaults.fdx = on; break; @@ -793,6 +832,24 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on) SSL_DisableDefaultExportCipherSuites(); break; + case SSL_BYPASS_PKCS11: + ssl_defaults.bypassPKCS11 = on; + break; + + case SSL_NO_LOCKS: + if (on && ssl_defaults.fdx) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (on && ssl_force_locks) + on = PR_FALSE; /* silent override */ + ssl_defaults.noLocks = on; + if (on) { + locksEverDisabled = PR_TRUE; + strcpy(lockStatus + LOCKSTATUS_OFFSET, "DISABLED."); + } + break; + default: PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; @@ -800,6 +857,20 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on) return SECSuccess; } +/* function tells us if the cipher suite is one that we no longer support. */ +static PRBool +ssl_IsRemovedCipherSuite(PRInt32 suite) +{ + switch (suite) { + case SSL_FORTEZZA_DMS_WITH_NULL_SHA: + case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA: + case SSL_FORTEZZA_DMS_WITH_RC4_128_SHA: + return PR_TRUE; + default: + return PR_FALSE; + } +} + /* Part of the public NSS API. * Since this is a global (not per-socket) setting, we cannot use the * HandshakeLock to protect this. Probably want a global lock. @@ -814,6 +885,8 @@ SSL_SetPolicy(long which, int policy) else if (which == SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA) which = SSL_RSA_FIPS_WITH_DES_CBC_SHA; } + if (ssl_IsRemovedCipherSuite(which)) + return SECSuccess; return SSL_CipherPolicySet(which, policy); } @@ -822,7 +895,9 @@ SSL_CipherPolicySet(PRInt32 which, PRInt32 policy) { SECStatus rv; - if (SSL_IS_SSL2_CIPHER(which)) { + if (ssl_IsRemovedCipherSuite(which)) { + rv = SECSuccess; + } else if (SSL_IS_SSL2_CIPHER(which)) { rv = ssl2_SetPolicy(which, policy); } else { rv = ssl3_SetPolicy((ssl3CipherSuite)which, policy); @@ -839,7 +914,10 @@ SSL_CipherPolicyGet(PRInt32 which, PRInt32 *oPolicy) PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } - if (SSL_IS_SSL2_CIPHER(which)) { + if (ssl_IsRemovedCipherSuite(which)) { + *oPolicy = SSL_NOT_ALLOWED; + rv = SECSuccess; + } else if (SSL_IS_SSL2_CIPHER(which)) { rv = ssl2_GetPolicy(which, oPolicy); } else { rv = ssl3_GetPolicy((ssl3CipherSuite)which, oPolicy); @@ -862,6 +940,8 @@ SSL_EnableCipher(long which, PRBool enabled) else if (which == SSL_RSA_OLDFIPS_WITH_DES_CBC_SHA) which = SSL_RSA_FIPS_WITH_DES_CBC_SHA; } + if (ssl_IsRemovedCipherSuite(which)) + return SECSuccess; return SSL_CipherPrefSetDefault(which, enabled); } @@ -869,7 +949,9 @@ SECStatus SSL_CipherPrefSetDefault(PRInt32 which, PRBool enabled) { SECStatus rv; - + + if (ssl_IsRemovedCipherSuite(which)) + return SECSuccess; if (enabled && ssl_defaults.noStepDown && SSL_IsExportCipherSuite(which)) { PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); return SECFailure; @@ -891,7 +973,10 @@ SSL_CipherPrefGetDefault(PRInt32 which, PRBool *enabled) PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } - if (SSL_IS_SSL2_CIPHER(which)) { + if (ssl_IsRemovedCipherSuite(which)) { + *enabled = PR_FALSE; + rv = SECSuccess; + } else if (SSL_IS_SSL2_CIPHER(which)) { rv = ssl2_CipherPrefGetDefault(which, enabled); } else { rv = ssl3_CipherPrefGetDefault((ssl3CipherSuite)which, enabled); @@ -909,7 +994,9 @@ SSL_CipherPrefSet(PRFileDesc *fd, PRInt32 which, PRBool enabled) SSL_DBG(("%d: SSL[%d]: bad socket in CipherPrefSet", SSL_GETPID(), fd)); return SECFailure; } - if (enabled && ss->noStepDown && SSL_IsExportCipherSuite(which)) { + if (ssl_IsRemovedCipherSuite(which)) + return SECSuccess; + if (enabled && ss->opt.noStepDown && SSL_IsExportCipherSuite(which)) { PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); return SECFailure; } @@ -936,7 +1023,10 @@ SSL_CipherPrefGet(PRFileDesc *fd, PRInt32 which, PRBool *enabled) *enabled = PR_FALSE; return SECFailure; } - if (SSL_IS_SSL2_CIPHER(which)) { + if (ssl_IsRemovedCipherSuite(which)) { + *enabled = PR_FALSE; + rv = SECSuccess; + } else if (SSL_IS_SSL2_CIPHER(which)) { rv = ssl2_CipherPrefGet(ss, which, enabled); } else { rv = ssl3_CipherPrefGet(ss, (ssl3CipherSuite)which, enabled); @@ -1002,7 +1092,7 @@ SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd) if (model == NULL) { /* Just create a default socket if we're given NULL for the model */ - ns = ssl_NewSocket(); + ns = ssl_NewSocket((PRBool)(!ssl_defaults.noLocks)); } else { sslSocket * ss = ssl_FindSocket(model); if (ss == NULL) { @@ -1087,8 +1177,8 @@ ssl_Accept(PRFileDesc *fd, PRNetAddr *sockaddr, PRIntervalTime timeout) /* Now start server connection handshake with client. ** Don't need locks here because nobody else has a reference to ns yet. */ - if ( ns->useSecurity ) { - if ( ns->handshakeAsClient ) { + if ( ns->opt.useSecurity ) { + if ( ns->opt.handshakeAsClient ) { ns->handshake = ssl2_BeginClientHandshake; ss->handshaking = sslHandshakingAsClient; } else { @@ -1244,7 +1334,7 @@ ssl_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags, } SSL_LOCK_READER(ss); ss->rTimeout = timeout; - if (!ss->fdx) + if (!ss->opt.fdx) ss->wTimeout = timeout; rv = (*ss->ops->recv)(ss, (unsigned char*)buf, len, flags); SSL_UNLOCK_READER(ss); @@ -1265,7 +1355,7 @@ ssl_Send(PRFileDesc *fd, const void *buf, PRInt32 len, PRIntn flags, } SSL_LOCK_WRITER(ss); ss->wTimeout = timeout; - if (!ss->fdx) + if (!ss->opt.fdx) ss->rTimeout = timeout; rv = (*ss->ops->send)(ss, (const unsigned char*)buf, len, flags); SSL_UNLOCK_WRITER(ss); @@ -1285,7 +1375,7 @@ ssl_Read(PRFileDesc *fd, void *buf, PRInt32 len) } SSL_LOCK_READER(ss); ss->rTimeout = PR_INTERVAL_NO_TIMEOUT; - if (!ss->fdx) + if (!ss->opt.fdx) ss->wTimeout = PR_INTERVAL_NO_TIMEOUT; rv = (*ss->ops->read)(ss, (unsigned char*)buf, len); SSL_UNLOCK_READER(ss); @@ -1305,7 +1395,7 @@ ssl_Write(PRFileDesc *fd, const void *buf, PRInt32 len) } SSL_LOCK_WRITER(ss); ss->wTimeout = PR_INTERVAL_NO_TIMEOUT; - if (!ss->fdx) + if (!ss->opt.fdx) ss->rTimeout = PR_INTERVAL_NO_TIMEOUT; rv = (*ss->ops->write)(ss, (const unsigned char*)buf, len); SSL_UNLOCK_WRITER(ss); @@ -1384,6 +1474,29 @@ SSL_SetSockPeerID(PRFileDesc *fd, char *peerID) return SECSuccess; } +SECStatus PR_CALLBACK +ssl_SetTimeout(PRFileDesc *fd, PRIntervalTime timeout) +{ + sslSocket *ss; + + ss = ssl_GetPrivate(fd); + if (!ss) { + SSL_DBG(("%d: SSL[%d]: bad socket in SetTimeout", SSL_GETPID(), fd)); + return SECFailure; + } + SSL_LOCK_READER(ss); + ss->rTimeout = timeout; + if (ss->opt.fdx) { + SSL_LOCK_WRITER(ss); + } + ss->wTimeout = timeout; + if (ss->opt.fdx) { + SSL_UNLOCK_WRITER(ss); + } + SSL_UNLOCK_READER(ss); + return SECSuccess; +} + #define PR_POLL_RW (PR_POLL_WRITE | PR_POLL_READ) static PRInt16 PR_CALLBACK @@ -1401,7 +1514,7 @@ ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *p_out_flags) return 0; /* don't poll on this socket */ } - if (ss->useSecurity && + if (ss->opt.useSecurity && ss->handshaking != sslHandshakingUndetermined && !ss->firstHsDone && (how_flags & PR_POLL_RW)) { @@ -1843,38 +1956,88 @@ loser: return PR_FAILURE; } +/* if this fails, caller must destroy socket. */ +static SECStatus +ssl_MakeLocks(sslSocket *ss) +{ + ss->firstHandshakeLock = PZ_NewMonitor(nssILockSSL); + if (!ss->firstHandshakeLock) + goto loser; + ss->ssl3HandshakeLock = PZ_NewMonitor(nssILockSSL); + if (!ss->ssl3HandshakeLock) + goto loser; + ss->specLock = NSSRWLock_New(SSL_LOCK_RANK_SPEC, NULL); + if (!ss->specLock) + goto loser; + ss->recvBufLock = PZ_NewMonitor(nssILockSSL); + if (!ss->recvBufLock) + goto loser; + ss->xmitBufLock = PZ_NewMonitor(nssILockSSL); + if (!ss->xmitBufLock) + goto loser; + ss->writerThread = NULL; + if (ssl_lock_readers) { + ss->recvLock = PZ_NewLock(nssILockSSL); + if (!ss->recvLock) + goto loser; + ss->sendLock = PZ_NewLock(nssILockSSL); + if (!ss->sendLock) + goto loser; + } + return SECSuccess; +loser: + ssl_DestroyLocks(ss); + return SECFailure; +} + +#if (defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_BEOS)) && !defined(_WIN32_WCE) +#define NSS_HAVE_GETENV 1 +#endif + /* ** Create a newsocket structure for a file descriptor. */ static sslSocket * -ssl_NewSocket(void) +ssl_NewSocket(PRBool makeLocks) { sslSocket *ss; -#ifdef DEBUG -#if (defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_BEOS)) && !defined(_WIN32_WCE) +#if defined( NSS_HAVE_GETENV ) static int firsttime = 1; if (firsttime) { + char * ev; firsttime = 0; - { - char *ev = getenv("SSLDEBUG"); - if (ev && ev[0]) { - ssl_debug = atoi(ev); - SSL_TRACE(("SSL: debugging set to %d", ssl_debug)); - } - } +#ifdef DEBUG #ifdef TRACE - { - char *ev = getenv("SSLTRACE"); - if (ev && ev[0]) { - ssl_trace = atoi(ev); - SSL_TRACE(("SSL: tracing set to %d", ssl_trace)); - } + ev = getenv("SSLTRACE"); + if (ev && ev[0]) { + ssl_trace = atoi(ev); + SSL_TRACE(("SSL: tracing set to %d", ssl_trace)); } #endif /* TRACE */ - } -#endif /* XP_UNIX || XP_WIN32 */ + ev = getenv("SSLDEBUG"); + if (ev && ev[0]) { + ssl_debug = atoi(ev); + SSL_TRACE(("SSL: debugging set to %d", ssl_debug)); + } #endif /* DEBUG */ + ev = getenv("SSLBYPASS"); + if (ev && ev[0]) { + ssl_defaults.bypassPKCS11 = (ev[0] == '1'); + SSL_TRACE(("SSL: bypass default set to %d", \ + ssl_defaults.bypassPKCS11)); + } + ev = getenv("SSLFORCELOCKS"); + if (ev && ev[0] == '1') { + ssl_force_locks = PR_TRUE; + ssl_defaults.noLocks = 0; + strcpy(lockStatus + LOCKSTATUS_OFFSET, "FORCED. "); + SSL_TRACE(("SSL: force_locks set to %d", ssl_force_locks)); + } + } +#endif /* NSS_HAVE_GETENV */ + if (ssl_force_locks) + makeLocks = PR_TRUE; /* Make a new socket and get it ready */ ss = (sslSocket*) PORT_ZAlloc(sizeof(sslSocket)); @@ -1885,20 +2048,10 @@ ssl_NewSocket(void) int i; SECStatus status; - ss->useSecurity = ssl_defaults.useSecurity; - ss->useSocks = PR_FALSE; - ss->requestCertificate = ssl_defaults.requestCertificate; - ss->requireCertificate = ssl_defaults.requireCertificate; - ss->handshakeAsClient = ssl_defaults.handshakeAsClient; - ss->handshakeAsServer = ssl_defaults.handshakeAsServer; - ss->enableSSL2 = ssl_defaults.enableSSL2; - ss->enableSSL3 = ssl_defaults.enableSSL3; - ss->enableTLS = ssl_defaults.enableTLS ; - ss->fdx = ssl_defaults.fdx; - ss->v2CompatibleHello = ssl_defaults.v2CompatibleHello; - ss->detectRollBack = ssl_defaults.detectRollBack; - ss->noStepDown = ssl_defaults.noStepDown; - ss->noCache = ssl_defaults.noCache; + ss->opt = ssl_defaults; + ss->opt.useSocks = PR_FALSE; + ss->opt.noLocks = !makeLocks; + ss->peerID = NULL; ss->rTimeout = PR_INTERVAL_NO_TIMEOUT; ss->wTimeout = PR_INTERVAL_NO_TIMEOUT; @@ -1912,7 +2065,7 @@ ssl_NewSocket(void) sslServerCerts * sc = ss->serverCerts + i; sc->serverCert = NULL; sc->serverCertChain = NULL; - sc->serverKey = NULL; + sc->serverKeyPair = NULL; sc->serverKeyBits = 0; } ss->stepDownKeyPair = NULL; @@ -1930,25 +2083,14 @@ ssl_NewSocket(void) ssl2_InitSocketPolicy(ss); ssl3_InitSocketPolicy(ss); - ss->firstHandshakeLock = PZ_NewMonitor(nssILockSSL); - if (!ss->firstHandshakeLock) goto loser; - ss->ssl3HandshakeLock = PZ_NewMonitor(nssILockSSL); - if (!ss->ssl3HandshakeLock) goto loser; - ss->specLock = NSSRWLock_New(SSL_LOCK_RANK_SPEC, NULL); - if (!ss->specLock) goto loser; - ss->recvBufLock = PZ_NewMonitor(nssILockSSL); - if (!ss->recvBufLock) goto loser; - ss->xmitBufLock = PZ_NewMonitor(nssILockSSL); - if (!ss->xmitBufLock) goto loser; - ss->writerThread = NULL; - if (ssl_lock_readers) { - ss->recvLock = PZ_NewLock(nssILockSSL); - if (!ss->recvLock) goto loser; - ss->sendLock = PZ_NewLock(nssILockSSL); - if (!ss->sendLock) goto loser; + if (makeLocks) { + status = ssl_MakeLocks(ss); + if (status != SECSuccess) + goto loser; } status = ssl_CreateSecurityInfo(ss); - if (status != SECSuccess) goto loser; + if (status != SECSuccess) + goto loser; status = ssl_InitGather(&ss->gs); if (status != SECSuccess) { loser: diff --git a/security/nss/lib/ssl/sslt.h b/security/nss/lib/ssl/sslt.h index 0223ee2ad..052339b7d 100644 --- a/security/nss/lib/ssl/sslt.h +++ b/security/nss/lib/ssl/sslt.h @@ -66,7 +66,7 @@ typedef enum { ssl_kea_null = 0, ssl_kea_rsa = 1, ssl_kea_dh = 2, - ssl_kea_fortezza = 3, + ssl_kea_fortezza = 3, /* deprecated, now unused */ ssl_kea_ecdh = 4, ssl_kea_size /* number of ssl_kea_ algorithms */ } SSLKEAType; @@ -79,7 +79,7 @@ typedef enum { #define kt_null ssl_kea_null #define kt_rsa ssl_kea_rsa #define kt_dh ssl_kea_dh -#define kt_fortezza ssl_kea_fortezza +#define kt_fortezza ssl_kea_fortezza /* deprecated, now unused */ #define kt_ecdh ssl_kea_ecdh #define kt_kea_size ssl_kea_size @@ -105,7 +105,7 @@ typedef enum { ssl_calg_des = 3, ssl_calg_3des = 4, ssl_calg_idea = 5, - ssl_calg_fortezza = 6, /* skipjack */ + ssl_calg_fortezza = 6, /* deprecated, now unused */ ssl_calg_aes = 7 /* coming soon */ } SSLCipherAlgorithm; diff --git a/security/nss/lib/util/Makefile b/security/nss/lib/util/Makefile index 97dfe0d7a..afe353d31 100644 --- a/security/nss/lib/util/Makefile +++ b/security/nss/lib/util/Makefile @@ -50,12 +50,6 @@ include manifest.mn include $(CORE_DEPTH)/coreconf/config.mk -ifeq ($(OS_TARGET),HP-UX) -ifneq ($(OS_TEST),ia64) - ASFILES += ret_cr16.s -endif -endif - ####################################################################### # (3) Include "component" configuration information. (OPTIONAL) # ####################################################################### diff --git a/security/nss/lib/util/quickder.c b/security/nss/lib/util/quickder.c index 33b251272..29a582147 100644 --- a/security/nss/lib/util/quickder.c +++ b/security/nss/lib/util/quickder.c @@ -113,12 +113,9 @@ static SECStatus GetItem(SECItem* src, SECItem* dest, PRBool includeTag) /* reaching the end of the buffer is not an error */ dest->data = NULL; dest->len = 0; - dest->type = siBuffer; - return SECSuccess; } - dest->type = siBuffer; dest->data = definite_length_decoder(src->data, src->len, &dest->len, includeTag); if (dest->data == NULL) @@ -862,7 +859,12 @@ static SECStatus DecodeItem(void* dest, SECItem* destItem = (SECItem*) ((char*)dest + templateEntry->offset); if (destItem) { - *(destItem) = temp; + /* we leave the type alone in the destination SECItem. + If part of the destination was allocated by the decoder, in + cases of POINTER, SET OF and SEQUENCE OF, then type is set to + siBuffer due to the use of PORT_ArenaZAlloc*/ + destItem->data = temp.data; + destItem->len = temp.len; } else { diff --git a/security/nss/lib/util/secasn1.h b/security/nss/lib/util/secasn1.h index 5e4779d57..462aaac23 100644 --- a/security/nss/lib/util/secasn1.h +++ b/security/nss/lib/util/secasn1.h @@ -92,6 +92,13 @@ extern SECStatus SEC_ASN1Decode(PRArenaPool *pool, void *dest, const SEC_ASN1Template *t, const char *buf, long len); +/* Both classic ASN.1 and QuickDER have a feature that removes leading zeroes + out of SEC_ASN1_INTEGER if the caller sets siUnsignedInteger in the type + field of the target SECItem prior to calling the decoder. Otherwise, the + type field is ignored and untouched. For SECItem that are dynamically + allocated (from POINTER, SET OF, SEQUENCE OF) the decoder sets the type + field to siBuffer. */ + extern SECStatus SEC_ASN1DecodeItem(PRArenaPool *pool, void *dest, const SEC_ASN1Template *t, const SECItem *src); |