summaryrefslogtreecommitdiff
path: root/security/nss/lib
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib')
-rw-r--r--security/nss/lib/certdb/certdb.c44
-rw-r--r--security/nss/lib/certdb/certdb.h7
-rw-r--r--security/nss/lib/certdb/certt.h15
-rw-r--r--security/nss/lib/certdb/genname.c2
-rw-r--r--security/nss/lib/certhigh/certhigh.c8
-rw-r--r--security/nss/lib/certhigh/certhtml.c15
-rw-r--r--security/nss/lib/certhigh/certreq.c165
-rw-r--r--security/nss/lib/certhigh/crlv2.c5
-rw-r--r--security/nss/lib/certhigh/ocsp.c7
-rw-r--r--security/nss/lib/ckfw/builtins/Makefile27
-rw-r--r--security/nss/lib/ckfw/builtins/nssckbi.h7
-rw-r--r--security/nss/lib/ckfw/capi/Makefile105
-rw-r--r--security/nss/lib/ckfw/capi/README7
-rw-r--r--security/nss/lib/ckfw/capi/anchor.c55
-rw-r--r--security/nss/lib/ckfw/capi/cfind.c595
-rw-r--r--security/nss/lib/ckfw/capi/cinst.c148
-rw-r--r--security/nss/lib/ckfw/capi/ckcapi.h309
-rw-r--r--security/nss/lib/ckfw/capi/ckcapiver.c59
-rw-r--r--security/nss/lib/ckfw/capi/cobject.c2346
-rw-r--r--security/nss/lib/ckfw/capi/config.mk71
-rw-r--r--security/nss/lib/ckfw/capi/constants.c98
-rw-r--r--security/nss/lib/ckfw/capi/crsa.c748
-rw-r--r--security/nss/lib/ckfw/capi/csession.c131
-rw-r--r--security/nss/lib/ckfw/capi/cslot.c129
-rw-r--r--security/nss/lib/ckfw/capi/ctoken.c246
-rw-r--r--security/nss/lib/ckfw/capi/manifest.mn66
-rw-r--r--security/nss/lib/ckfw/capi/nsscapi.def58
-rw-r--r--security/nss/lib/ckfw/capi/nsscapi.h75
-rw-r--r--security/nss/lib/ckfw/capi/nsscapi.rc97
-rw-r--r--security/nss/lib/ckfw/capi/staticobj.c74
-rw-r--r--security/nss/lib/ckfw/ckfwm.h7
-rw-r--r--security/nss/lib/ckfw/manifest.mn1
-rw-r--r--security/nss/lib/ckfw/mutex.c56
-rw-r--r--security/nss/lib/ckfw/wrap.c49
-rw-r--r--security/nss/lib/crmf/cmmfrec.c32
-rw-r--r--security/nss/lib/cryptohi/hasht.h4
-rw-r--r--security/nss/lib/cryptohi/keyhi.h2
-rw-r--r--security/nss/lib/cryptohi/manifest.mn5
-rw-r--r--security/nss/lib/cryptohi/sechash.c28
-rw-r--r--security/nss/lib/cryptohi/seckey.c30
-rw-r--r--security/nss/lib/cryptohi/secsign.c65
-rw-r--r--security/nss/lib/cryptohi/secvfy.c142
-rw-r--r--security/nss/lib/freebl/Makefile354
-rw-r--r--security/nss/lib/freebl/aeskeywrap.c59
-rw-r--r--security/nss/lib/freebl/alg2268.c66
-rw-r--r--security/nss/lib/freebl/alghmac.c (renamed from security/nss/lib/softoken/alghmac.c)79
-rw-r--r--security/nss/lib/freebl/alghmac.h (renamed from security/nss/lib/softoken/alghmac.h)11
-rw-r--r--security/nss/lib/freebl/arcfour-amd64-gas.s4
-rw-r--r--security/nss/lib/freebl/arcfour.c46
-rw-r--r--security/nss/lib/freebl/blapi.h74
-rw-r--r--security/nss/lib/freebl/blapit.h23
-rw-r--r--security/nss/lib/freebl/config.mk67
-rw-r--r--security/nss/lib/freebl/desblapi.c34
-rw-r--r--security/nss/lib/freebl/dsa.c167
-rw-r--r--security/nss/lib/freebl/ec.c177
-rw-r--r--security/nss/lib/freebl/ecl/ec2.h3
-rw-r--r--security/nss/lib/freebl/ecl/ec2_aff.c76
-rw-r--r--security/nss/lib/freebl/ecl/ecl-curve.h4
-rw-r--r--security/nss/lib/freebl/ecl/ecl-priv.h1
-rw-r--r--security/nss/lib/freebl/ecl/ecl.c22
-rw-r--r--security/nss/lib/freebl/ecl/ecl.h7
-rw-r--r--security/nss/lib/freebl/ecl/ecl_mult.c45
-rw-r--r--security/nss/lib/freebl/ecl/ecp.h3
-rw-r--r--security/nss/lib/freebl/ecl/ecp_aff.c73
-rw-r--r--security/nss/lib/freebl/ecl/ecp_jm.c2
-rw-r--r--security/nss/lib/freebl/ecl/tests/ec2_test.c13
-rw-r--r--security/nss/lib/freebl/ecl/tests/ecp_test.c13
-rw-r--r--security/nss/lib/freebl/freebl.def58
-rw-r--r--security/nss/lib/freebl/freeblver.c56
-rw-r--r--security/nss/lib/freebl/ldvector.c48
-rw-r--r--security/nss/lib/freebl/loader.c594
-rw-r--r--security/nss/lib/freebl/loader.h74
-rw-r--r--security/nss/lib/freebl/manifest.mn62
-rw-r--r--security/nss/lib/freebl/md2.c5
-rw-r--r--security/nss/lib/freebl/md5.c25
-rw-r--r--security/nss/lib/freebl/mpi/Makefile3
-rw-r--r--security/nss/lib/freebl/mpi/mp_comba.c1306
-rw-r--r--security/nss/lib/freebl/mpi/mp_comba_amd64_sun.s16097
-rw-r--r--security/nss/lib/freebl/mpi/mpcpucache.c773
-rw-r--r--security/nss/lib/freebl/mpi/mpcpucache_amd64.s891
-rw-r--r--security/nss/lib/freebl/mpi/mpcpucache_x86.s931
-rw-r--r--security/nss/lib/freebl/mpi/mpi-priv.h29
-rw-r--r--security/nss/lib/freebl/mpi/mpi.c48
-rw-r--r--security/nss/lib/freebl/mpi/mpi_amd64_gas.s4
-rw-r--r--security/nss/lib/freebl/mpi/mpmontg.c632
-rw-r--r--security/nss/lib/freebl/mpi/mpv_sparcv8.s148
-rw-r--r--security/nss/lib/freebl/mpi/mpv_sparcv8x.s175
-rw-r--r--security/nss/lib/freebl/mpi/target.mk3
-rw-r--r--security/nss/lib/freebl/pqg.c13
-rw-r--r--security/nss/lib/freebl/prng_fips1861.c355
-rw-r--r--security/nss/lib/freebl/rawhash.c (renamed from security/nss/lib/softoken/rawhash.c)42
-rw-r--r--security/nss/lib/freebl/ret_cr16.s (renamed from security/nss/lib/util/ret_cr16.s)0
-rw-r--r--security/nss/lib/freebl/rijndael.c68
-rw-r--r--security/nss/lib/freebl/rijndael.h41
-rw-r--r--security/nss/lib/freebl/secmpi.h1
-rw-r--r--security/nss/lib/freebl/sha-fast-amd64-sun.s2142
-rw-r--r--security/nss/lib/freebl/sha512.c15
-rw-r--r--security/nss/lib/freebl/sha_fast.c500
-rw-r--r--security/nss/lib/freebl/sha_fast.h130
-rw-r--r--security/nss/lib/freebl/tlsprfalg.c164
-rw-r--r--security/nss/lib/manifest.mn4
-rw-r--r--security/nss/lib/nss/config.mk10
-rw-r--r--security/nss/lib/nss/nss.def15
-rw-r--r--security/nss/lib/nss/nss.h47
-rw-r--r--security/nss/lib/nss/nssinit.c54
-rw-r--r--security/nss/lib/pk11wrap/manifest.mn5
-rw-r--r--security/nss/lib/pk11wrap/pk11akey.c894
-rw-r--r--security/nss/lib/pk11wrap/pk11cert.c394
-rw-r--r--security/nss/lib/pk11wrap/pk11err.c6
-rw-r--r--security/nss/lib/pk11wrap/pk11load.c77
-rw-r--r--security/nss/lib/pk11wrap/pk11mech.c7
-rw-r--r--security/nss/lib/pk11wrap/pk11nobj.c152
-rw-r--r--security/nss/lib/pk11wrap/pk11obj.c44
-rw-r--r--security/nss/lib/pk11wrap/pk11pars.c4
-rw-r--r--security/nss/lib/pk11wrap/pk11pqg.c6
-rw-r--r--security/nss/lib/pk11wrap/pk11priv.h8
-rw-r--r--security/nss/lib/pk11wrap/pk11pub.h91
-rw-r--r--security/nss/lib/pk11wrap/pk11skey.c328
-rw-r--r--security/nss/lib/pk11wrap/pk11slot.c239
-rw-r--r--security/nss/lib/pk11wrap/pk11util.c273
-rw-r--r--security/nss/lib/pk11wrap/secmodi.h3
-rw-r--r--security/nss/lib/pk11wrap/secmodt.h1
-rw-r--r--security/nss/lib/pk11wrap/secmodti.h28
-rw-r--r--security/nss/lib/pkcs12/manifest.mn4
-rw-r--r--security/nss/lib/pkcs12/p12d.c59
-rw-r--r--security/nss/lib/pkcs12/p12e.c15
-rw-r--r--security/nss/lib/pkcs7/p7decode.c20
-rw-r--r--security/nss/lib/pkcs7/p7encode.c8
-rw-r--r--security/nss/lib/pkcs7/p7local.c24
-rw-r--r--security/nss/lib/pki/certificate.c99
-rw-r--r--security/nss/lib/pki/pkim.h7
-rw-r--r--security/nss/lib/pki/pkistore.c21
-rw-r--r--security/nss/lib/pki/pkitm.h10
-rw-r--r--security/nss/lib/pki/tdcache.c18
-rw-r--r--security/nss/lib/smime/cmscipher.c26
-rw-r--r--security/nss/lib/smime/cmsencdata.c10
-rw-r--r--security/nss/lib/smime/cmsenvdata.c10
-rw-r--r--security/nss/lib/smime/cmsrecinfo.c19
-rw-r--r--security/nss/lib/smime/cmsreclist.c3
-rw-r--r--security/nss/lib/smime/cmssiginfo.c20
-rw-r--r--security/nss/lib/smime/cmsutil.c10
-rw-r--r--security/nss/lib/smime/config.mk11
-rw-r--r--security/nss/lib/softoken/cdbhdl.h4
-rw-r--r--security/nss/lib/softoken/config.mk13
-rw-r--r--security/nss/lib/softoken/dbinit.c49
-rw-r--r--security/nss/lib/softoken/fipstest.c476
-rw-r--r--security/nss/lib/softoken/fipstokn.c114
-rw-r--r--security/nss/lib/softoken/keydb.c279
-rw-r--r--security/nss/lib/softoken/keydbi.h2
-rw-r--r--security/nss/lib/softoken/lowcert.c49
-rw-r--r--security/nss/lib/softoken/lowpbe.c6
-rw-r--r--security/nss/lib/softoken/manifest.mn3
-rw-r--r--security/nss/lib/softoken/pcert.h3
-rw-r--r--security/nss/lib/softoken/pcertdb.c103
-rw-r--r--security/nss/lib/softoken/pk11db.c18
-rw-r--r--security/nss/lib/softoken/pk11pars.h21
-rw-r--r--security/nss/lib/softoken/pkcs11.c886
-rw-r--r--security/nss/lib/softoken/pkcs11c.c337
-rw-r--r--security/nss/lib/softoken/pkcs11f.h14
-rw-r--r--security/nss/lib/softoken/pkcs11i.h119
-rw-r--r--security/nss/lib/softoken/pkcs11n.h10
-rw-r--r--security/nss/lib/softoken/pkcs11ni.h52
-rw-r--r--security/nss/lib/softoken/pkcs11t.h656
-rw-r--r--security/nss/lib/softoken/pkcs11u.c823
-rw-r--r--security/nss/lib/softoken/tlsprf.c126
-rw-r--r--security/nss/lib/ssl/config.mk38
-rw-r--r--security/nss/lib/ssl/derive.c481
-rw-r--r--security/nss/lib/ssl/manifest.mn6
-rw-r--r--security/nss/lib/ssl/nsskea.c6
-rw-r--r--security/nss/lib/ssl/preenc.h94
-rw-r--r--security/nss/lib/ssl/prelib.c197
-rw-r--r--security/nss/lib/ssl/ssl.h18
-rw-r--r--security/nss/lib/ssl/ssl3con.c4326
-rw-r--r--security/nss/lib/ssl/ssl3ecc.c673
-rw-r--r--security/nss/lib/ssl/ssl3gthr.c8
-rw-r--r--security/nss/lib/ssl/ssl3prot.h19
-rw-r--r--security/nss/lib/ssl/sslauth.c9
-rw-r--r--security/nss/lib/ssl/sslcon.c124
-rw-r--r--security/nss/lib/ssl/ssldef.c2
-rw-r--r--security/nss/lib/ssl/sslenum.c5
-rw-r--r--security/nss/lib/ssl/sslgathr.c14
-rw-r--r--security/nss/lib/ssl/sslimpl.h257
-rw-r--r--security/nss/lib/ssl/sslinfo.c59
-rw-r--r--security/nss/lib/ssl/sslnonce.c2
-rw-r--r--security/nss/lib/ssl/sslproto.h6
-rw-r--r--security/nss/lib/ssl/sslsecur.c135
-rw-r--r--security/nss/lib/ssl/sslsnce.c23
-rw-r--r--security/nss/lib/ssl/sslsock.c394
-rw-r--r--security/nss/lib/ssl/sslt.h6
-rw-r--r--security/nss/lib/util/Makefile6
-rw-r--r--security/nss/lib/util/quickder.c10
-rw-r--r--security/nss/lib/util/secasn1.h7
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(&notBeforeA, &val_a->notBefore) ||
+ SECSuccess != DER_DecodeTimeChoice(&notBeforeB, &val_b->notBefore) ||
+ SECSuccess != DER_DecodeTimeChoice(&notAfterA, &val_a->notAfter) ||
+ SECSuccess != DER_DecodeTimeChoice(&notAfterB, &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, &copyk->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,&copyk->u.ec.DEREncodedParams,
@@ -1502,7 +1503,6 @@ SECKEY_CopyPublicKey(SECKEYPublicKey *pubk)
rv = SECITEM_CopyItem(arena,&copyk->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(&params, PR_FALSE);
break;
-#ifdef NSS_ENABLE_ECC
case ecKey:
rv = SECITEM_CopyItem(arena, &params,
&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, &params->prime) );
- CHECKOK( SECITEM_CopyItem(arena, &key->params.subPrime, &params->subPrime));
- CHECKOK( SECITEM_CopyItem(arena, &key->params.base, &params->base) );
+ CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.prime,
+ &params->prime) );
+ CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.subPrime,
+ &params->subPrime) );
+ CHECK_MPI_OK( SECITEM_CopyItem(arena, &key->params.base, &params->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, &param);
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, &paramStrings.tokens[i],
+ crv = SFTK_SlotInit(paramStrings.configdir,
+ &paramStrings.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, &paramStrings, 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,
+ &paramStrings.tokens[0], moduleIndex);
+ } else {
+ crv = SFTK_SlotInit(paramStrings.configdir,
+ &paramStrings.tokens[0], moduleIndex);
+ }
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+loser:
+ secmod_freeParams(&paramStrings);
+ 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, &params, &vfy);
+ rv = PQG_ParamGen(j, &params, &vfy);
} else {
- rv = PQG_ParamGenSeedLen(primeBits,seedBits/8, &params, &vfy);
+ rv = PQG_ParamGenSeedLen(j,seedBits/8, &params, &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, &params, 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, &params,
@@ -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, &param, &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, &param, 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,
- &param, 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, &param, 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, &param, &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, &param);
- 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, &param);
+ 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);