diff --git a/mozilla/security/nss/lib/certhigh/ocsp.c b/mozilla/security/nss/lib/certhigh/ocsp.c index 5a8273e5d7b..048708ea0c5 100644 --- a/mozilla/security/nss/lib/certhigh/ocsp.c +++ b/mozilla/security/nss/lib/certhigh/ocsp.c @@ -6,7 +6,7 @@ * Implementation of OCSP services, for both client and server. * (XXX, really, mostly just for client right now, but intended to do both.) * - * $Id: ocsp.c,v 1.78 2013-02-15 17:53:24 kaie%kuix.de Exp $ + * $Id: ocsp.c,v 1.79 2013-02-15 17:56:18 kaie%kuix.de Exp $ */ #include "prerror.h" @@ -1572,7 +1572,7 @@ CERT_DestroyOCSPCertID(CERTOCSPCertID* certID) * results in a NULL being returned (and an appropriate error set). */ -static SECItem * +SECItem * ocsp_DigestValue(PRArenaPool *arena, SECOidTag digestAlg, SECItem *fill, const SECItem *src) { diff --git a/mozilla/security/nss/lib/certhigh/ocspi.h b/mozilla/security/nss/lib/certhigh/ocspi.h index 1257240826f..aab1672cd51 100644 --- a/mozilla/security/nss/lib/certhigh/ocspi.h +++ b/mozilla/security/nss/lib/certhigh/ocspi.h @@ -4,7 +4,7 @@ /* * ocspi.h - NSS internal interfaces to OCSP code * - * $Id: ocspi.h,v 1.13 2012-12-12 19:29:40 wtc%google.com Exp $ + * $Id: ocspi.h,v 1.14 2013-02-15 17:56:18 kaie%kuix.de Exp $ */ #ifndef _OCSPI_H_ @@ -19,6 +19,10 @@ ocsp_GetResponseData(CERTOCSPResponse *response, SECItem **tbsResponseDataDER); ocspSignature * ocsp_GetResponseSignature(CERTOCSPResponse *response); +SECItem * +ocsp_DigestValue(PRArenaPool *arena, SECOidTag digestAlg, + SECItem *fill, const SECItem *src); + PRBool ocsp_CertIsOCSPDefaultResponder(CERTCertDBHandle *handle, CERTCertificate *cert); diff --git a/mozilla/security/nss/lib/certhigh/ocspsig.c b/mozilla/security/nss/lib/certhigh/ocspsig.c index 99298ffa4bc..775c1241187 100644 --- a/mozilla/security/nss/lib/certhigh/ocspsig.c +++ b/mozilla/security/nss/lib/certhigh/ocspsig.c @@ -355,6 +355,8 @@ CERT_CreateOCSPSingleResponseRevoked( return ocsp_CreateSingleResponse(arena, id, cs, thisUpdate, nextUpdate); } +/* responderCert == 0 means: + * create a response with an invalid signature (for testing purposes) */ SECItem* CERT_CreateEncodedOCSPSuccessResponse( PLArenaPool *arena, @@ -377,7 +379,7 @@ CERT_CreateEncodedOCSPSuccessResponse( SECKEYPrivateKey *privKey = NULL; SECItem *result = NULL; - if (!arena || !responderCert || !responses) { + if (!arena || !responses) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return NULL; } @@ -414,58 +416,106 @@ CERT_CreateEncodedOCSPSuccessResponse( if (DER_TimeToGeneralizedTimeArena(tmpArena, &rd->producedAt, producedAt) != SECSuccess) goto done; - rid->responderIDType = responderIDType; - if (responderIDType == ocspResponderID_byName) { - responderIDTemplate = ocsp_ResponderIDByNameTemplate; - if (CERT_CopyName(tmpArena, &rid->responderIDValue.name, - &responderCert->subject) != SECSuccess) - goto done; + + if (!responderCert) { + /* use invalid signature for testing purposes */ + char dummyChar = 'd'; + SECItem dummy; + + dummy.len = 1; + dummy.data = &dummyChar; + + /* it's easier to produdce a keyHash out of nowhere, + * than to produce an encoded subject, + * so for our dummy response we always use byKey + */ + + rid->responderIDType = ocspResponderID_byKey; + if (!ocsp_DigestValue(tmpArena, SEC_OID_SHA1, &rid->responderIDValue.keyHash, + &dummy)) + goto done; + + if (!SEC_ASN1EncodeItem(tmpArena, &rd->derResponderID, rid, + ocsp_ResponderIDByKeyTemplate)) + goto done; + + br->tbsResponseData = rd; + + if (!SEC_ASN1EncodeItem(tmpArena, &br->tbsResponseDataDER, br->tbsResponseData, + ocsp_myResponseDataTemplate)) + goto done; + + br->responseSignature.derCerts = PORT_ArenaNewArray(tmpArena, SECItem*, 1); + if (!br->responseSignature.derCerts) + goto done; + br->responseSignature.derCerts[0] = NULL; + + algID = SEC_GetSignatureAlgorithmOidTag(rsaKey, SEC_OID_SHA1); + if (algID == SEC_OID_UNKNOWN) + goto done; + + /* match the regular signature code, which doesn't use the arena */ + if (!SECITEM_AllocItem(NULL, &br->responseSignature.signature, 1)) + goto done; + PORT_Memcpy(br->responseSignature.signature.data, &dummyChar, 1); + + /* convert len-in-bytes to len-in-bits */ + br->responseSignature.signature.len = br->responseSignature.signature.len << 3; } else { - responderIDTemplate = ocsp_ResponderIDByKeyTemplate; - if (!CERT_GetSPKIDigest(tmpArena, responderCert, SEC_OID_SHA1, - &rid->responderIDValue.keyHash)) - goto done; + rid->responderIDType = responderIDType; + if (responderIDType == ocspResponderID_byName) { + responderIDTemplate = ocsp_ResponderIDByNameTemplate; + if (CERT_CopyName(tmpArena, &rid->responderIDValue.name, + &responderCert->subject) != SECSuccess) + goto done; + } + else { + responderIDTemplate = ocsp_ResponderIDByKeyTemplate; + if (!CERT_GetSPKIDigest(tmpArena, responderCert, SEC_OID_SHA1, + &rid->responderIDValue.keyHash)) + goto done; + } + + if (!SEC_ASN1EncodeItem(tmpArena, &rd->derResponderID, rid, + responderIDTemplate)) + goto done; + + br->tbsResponseData = rd; + + if (!SEC_ASN1EncodeItem(tmpArena, &br->tbsResponseDataDER, br->tbsResponseData, + ocsp_myResponseDataTemplate)) + goto done; + + br->responseSignature.derCerts = PORT_ArenaNewArray(tmpArena, SECItem*, 1); + if (!br->responseSignature.derCerts) + goto done; + br->responseSignature.derCerts[0] = NULL; + + privKey = PK11_FindKeyByAnyCert(responderCert, wincx); + if (!privKey) + goto done; + + algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, SEC_OID_SHA1); + if (algID == SEC_OID_UNKNOWN) + goto done; + + if (SEC_SignData(&br->responseSignature.signature, + br->tbsResponseDataDER.data, br->tbsResponseDataDER.len, + privKey, algID) + != SECSuccess) + goto done; + + /* convert len-in-bytes to len-in-bits */ + br->responseSignature.signature.len = br->responseSignature.signature.len << 3; + + /* br->responseSignature.signature wasn't allocated from arena, + * we must free it when done. */ } - if (!SEC_ASN1EncodeItem(tmpArena, &rd->derResponderID, rid, - responderIDTemplate)) - goto done; - - br->tbsResponseData = rd; - - if (!SEC_ASN1EncodeItem(tmpArena, &br->tbsResponseDataDER, br->tbsResponseData, - ocsp_myResponseDataTemplate)) - goto done; - - br->responseSignature.derCerts = PORT_ArenaNewArray(tmpArena, SECItem*, 1); - if (!br->responseSignature.derCerts) - goto done; - br->responseSignature.derCerts[0] = NULL; - - privKey = PK11_FindKeyByAnyCert(responderCert, wincx); - if (!privKey) - goto done; - - algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, SEC_OID_SHA1); - if (algID == SEC_OID_UNKNOWN) - goto done; - - if (SEC_SignData(&br->responseSignature.signature, - br->tbsResponseDataDER.data, br->tbsResponseDataDER.len, - privKey, algID) - != SECSuccess) - goto done; - - /* convert len-in-bytes to len-in-bits */ - br->responseSignature.signature.len = br->responseSignature.signature.len << 3; - - /* br->responseSignature.signature wasn't allocated from arena, - * we must free it when done. */ - if (SECOID_SetAlgorithmID(tmpArena, &br->responseSignature.signatureAlgorithm, algID, 0) - != SECSuccess) - goto done; + != SECSuccess) + goto done; if (!SEC_ASN1EncodeItem(tmpArena, &rb->response, br, ocsp_EncodeBasicOCSPResponseTemplate)) diff --git a/mozilla/security/nss/lib/ssl/ssl.def b/mozilla/security/nss/lib/ssl/ssl.def index 81c97a7caa8..15dbfede7b8 100644 --- a/mozilla/security/nss/lib/ssl/ssl.def +++ b/mozilla/security/nss/lib/ssl/ssl.def @@ -159,6 +159,7 @@ SSL_SetSRTPCiphers; ;+NSS_3.14.2 { # NSS 3.14.2 release ;+ global: SSL_PeerStapledOCSPResponses; +SSL_SetStapledOCSPResponses; ;+ local: ;+*; ;+}; diff --git a/mozilla/security/nss/lib/ssl/ssl.h b/mozilla/security/nss/lib/ssl/ssl.h index 58bee4f353f..2bd5e54146c 100644 --- a/mozilla/security/nss/lib/ssl/ssl.h +++ b/mozilla/security/nss/lib/ssl/ssl.h @@ -4,7 +4,7 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: ssl.h,v 1.61 2013-02-15 17:55:41 kaie%kuix.de Exp $ */ +/* $Id: ssl.h,v 1.62 2013-02-15 17:56:19 kaie%kuix.de Exp $ */ #ifndef __ssl_h_ #define __ssl_h_ @@ -416,6 +416,17 @@ SSL_IMPORT CERTCertificate *SSL_PeerCertificate(PRFileDesc *fd); */ SSL_IMPORT const SECItemArray * SSL_PeerStapledOCSPResponses(PRFileDesc *fd); +/* SSL_SetStapledOCSPResponses stores an array of one or multiple OCSP responses + * in the fd's data, which may be sent as part of a server side cert_status + * handshake message. + * If takeOwnership is false, the function will duplicate the responses. + * If takeOwnership is true, the ownership of responses is transfered into the + * SSL library, and the caller must stop using it. + */ +SSL_IMPORT SECStatus +SSL_SetStapledOCSPResponses(PRFileDesc *fd, SECItemArray *responses, + PRBool takeOwnership); + /* ** Authenticate certificate hook. Called when a certificate comes in ** (because of SSL_REQUIRE_CERTIFICATE in SSL_Enable) to authenticate the diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/ssl/ssl3con.c index f6b967ca7b4..b02d93ec545 100644 --- a/mozilla/security/nss/lib/ssl/ssl3con.c +++ b/mozilla/security/nss/lib/ssl/ssl3con.c @@ -5,7 +5,7 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: ssl3con.c,v 1.203 2013-02-15 17:55:41 kaie%kuix.de Exp $ */ +/* $Id: ssl3con.c,v 1.204 2013-02-15 17:56:19 kaie%kuix.de Exp $ */ /* TODO(ekr): Implement HelloVerifyRequest on server side. OK for now. */ @@ -49,6 +49,7 @@ static SECStatus ssl3_DeriveConnectionKeysPKCS11(sslSocket *ss); static SECStatus ssl3_HandshakeFailure( sslSocket *ss); static SECStatus ssl3_InitState( sslSocket *ss); static SECStatus ssl3_SendCertificate( sslSocket *ss); +static SECStatus ssl3_SendCertificateStatus( sslSocket *ss); static SECStatus ssl3_SendEmptyCertificate( sslSocket *ss); static SECStatus ssl3_SendCertificateRequest(sslSocket *ss); static SECStatus ssl3_SendNextProto( sslSocket *ss); @@ -6491,6 +6492,10 @@ ssl3_SendServerHelloSequence(sslSocket *ss) if (rv != SECSuccess) { return rv; /* error code is set. */ } + rv = ssl3_SendCertificateStatus(ss); + if (rv != SECSuccess) { + return rv; /* error code is set. */ + } /* We have to do this after the call to ssl3_SendServerHello, * because kea_def is set up by ssl3_SendServerHello(). */ @@ -8433,6 +8438,52 @@ ssl3_SendCertificate(sslSocket *ss) return SECSuccess; } +/* + * Used by server only. + * single-stapling, send only a single cert status + */ +static SECStatus +ssl3_SendCertificateStatus(sslSocket *ss) +{ + SECStatus rv; + CERTCertificateList *certChain; + int len = 0; + int i; + SSL3KEAType certIndex; + + SSL_TRC(3, ("%d: SSL3[%d]: send certificate status handshake", + SSL_GETPID(), ss->fd)); + + PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); + + if (!ssl3_ExtensionNegotiated(ss, ssl_cert_status_xtn)) + return SECSuccess; + + if (!ss->certStatusArray) + return SECSuccess; + + /* Use the array's first item only (single stapling) */ + len = 1 + ss->certStatusArray->items[0].len + 3; + + rv = ssl3_AppendHandshakeHeader(ss, certificate_status, len); + if (rv != SECSuccess) { + return rv; /* err set by AppendHandshake. */ + } + rv = ssl3_AppendHandshakeNumber(ss, 1 /*ocsp*/, 1); + if (rv != SECSuccess) + return rv; /* err set by AppendHandshake. */ + + rv = ssl3_AppendHandshakeVariable(ss, + ss->certStatusArray->items[0].data, + ss->certStatusArray->items[0].len, + 3); + if (rv != SECSuccess) + return rv; /* err set by AppendHandshake. */ + + return SECSuccess; +} + /* This is used to delete the CA certificates in the peer certificate chain * from the cert database after they've been validated. */ diff --git a/mozilla/security/nss/lib/ssl/ssl3ext.c b/mozilla/security/nss/lib/ssl/ssl3ext.c index a9e5e4655db..c1eede8307f 100644 --- a/mozilla/security/nss/lib/ssl/ssl3ext.c +++ b/mozilla/security/nss/lib/ssl/ssl3ext.c @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* TLS extension code moved here from ssl3ecc.c */ -/* $Id: ssl3ext.c,v 1.31 2013-02-15 17:52:45 kaie%kuix.de Exp $ */ +/* $Id: ssl3ext.c,v 1.32 2013-02-15 17:56:19 kaie%kuix.de Exp $ */ #include "nssrenam.h" #include "nss.h" @@ -61,6 +61,10 @@ static PRInt32 ssl3_SendUseSRTPXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes); static SECStatus ssl3_HandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data); +static SECStatus ssl3_ServerSendStatusRequestXtn(sslSocket * ss, + PRBool append, PRUint32 maxBytes); +static SECStatus ssl3_ServerHandleStatusRequestXtn(sslSocket *ss, + PRUint16 ex_type, SECItem *data); static SECStatus ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data); @@ -227,6 +231,7 @@ static const ssl3HelloExtensionHandler clientHelloHandlers[] = { { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, { ssl_next_proto_nego_xtn, &ssl3_ServerHandleNextProtoNegoXtn }, { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn }, + { ssl_cert_status_xtn, &ssl3_ServerHandleStatusRequestXtn }, { -1, NULL } }; @@ -669,6 +674,33 @@ ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type, return SECSuccess; } +static PRInt32 +ssl3_ServerSendStatusRequestXtn( + sslSocket * ss, + PRBool append, + PRUint32 maxBytes) +{ + PRInt32 extension_length; + SECStatus rv; + + if (!ss->certStatusArray) + return 0; + + extension_length = 2 + 2; + if (append && maxBytes >= extension_length) { + /* extension_type */ + rv = ssl3_AppendHandshakeNumber(ss, ssl_cert_status_xtn, 2); + if (rv != SECSuccess) + return -1; + /* length of extension_data */ + rv = ssl3_AppendHandshakeNumber(ss, 0, 2); + if (rv != SECSuccess) + return -1; + } + + return extension_length; +} + /* ssl3_ClientSendStatusRequestXtn builds the status_request extension on the * client side. See RFC 4366 section 3.6. */ static PRInt32 @@ -1705,6 +1737,22 @@ ssl3_SendRenegotiationInfoXtn( return needed; } +static SECStatus +ssl3_ServerHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type, + SECItem *data) +{ + SECStatus rv = SECSuccess; + PRUint32 len = 0; + + /* remember that we got this extension. */ + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; + PORT_Assert(ss->sec.isServer); + /* prepare to send back the appropriate response */ + rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type, + ssl3_ServerSendStatusRequestXtn); + return rv; +} + /* This function runs in both the client and server. */ static SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) diff --git a/mozilla/security/nss/lib/ssl/sslimpl.h b/mozilla/security/nss/lib/ssl/sslimpl.h index 9dd638a16d8..f73a7908625 100644 --- a/mozilla/security/nss/lib/ssl/sslimpl.h +++ b/mozilla/security/nss/lib/ssl/sslimpl.h @@ -5,7 +5,7 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: sslimpl.h,v 1.111 2013-02-15 17:55:41 kaie%kuix.de Exp $ */ +/* $Id: sslimpl.h,v 1.112 2013-02-15 17:56:19 kaie%kuix.de Exp $ */ #ifndef __sslimpl_h_ #define __sslimpl_h_ @@ -1178,6 +1178,7 @@ const unsigned char * preferredCipher; /* Configuration state for server sockets */ /* server cert and key for each KEA type */ sslServerCerts serverCerts[kt_kea_size]; + SECItemArray * certStatusArray; ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED]; ssl3KeyPair * ephemeralECDHKeyPair; /* for ECDHE-* handshake */ diff --git a/mozilla/security/nss/lib/ssl/sslsock.c b/mozilla/security/nss/lib/ssl/sslsock.c index 9577afab191..13663d90655 100644 --- a/mozilla/security/nss/lib/ssl/sslsock.c +++ b/mozilla/security/nss/lib/ssl/sslsock.c @@ -6,7 +6,7 @@ * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* $Id: sslsock.c,v 1.101 2013-02-15 17:55:41 kaie%kuix.de Exp $ */ +/* $Id: sslsock.c,v 1.102 2013-02-15 17:56:19 kaie%kuix.de Exp $ */ #include "seccomon.h" #include "cert.h" #include "keyhi.h" @@ -327,6 +327,8 @@ ssl_DupSocket(sslSocket *os) ssl3_GetKeyPairRef(os->stepDownKeyPair); ss->ephemeralECDHKeyPair = !os->ephemeralECDHKeyPair ? NULL : ssl3_GetKeyPairRef(os->ephemeralECDHKeyPair); + ss->certStatusArray = !os->certStatusArray ? NULL : + SECITEM_DupArray(NULL, os->certStatusArray); /* * XXX the preceding CERT_ and SECKEY_ functions can fail and return NULL. * XXX We should detect this, and not just march on with NULL pointers. @@ -438,6 +440,10 @@ ssl_DestroySocketContents(sslSocket *ss) ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair); ss->ephemeralECDHKeyPair = NULL; } + if (ss->certStatusArray) { + SECITEM_FreeArray(ss->certStatusArray, PR_TRUE); + ss->certStatusArray = NULL; + } SECITEM_FreeItem(&ss->opt.nextProtoNego, PR_FALSE); PORT_Assert(!ss->xtnData.sniNameArr); if (ss->xtnData.sniNameArr) { @@ -1688,6 +1694,13 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd) ss->ephemeralECDHKeyPair = ssl3_GetKeyPairRef(sm->ephemeralECDHKeyPair); } + if (sm->certStatusArray) { + if (ss->certStatusArray) { + SECITEM_FreeArray(ss->certStatusArray, PR_TRUE); + ss->certStatusArray = NULL; + } + ss->certStatusArray = SECITEM_DupArray(NULL, sm->certStatusArray); + } /* copy trust anchor names */ if (sm->ssl3.ca_list) { if (ss->ssl3.ca_list) { @@ -1872,7 +1885,7 @@ SSL_PeerStapledOCSPResponses(PRFileDesc *fd) sslSocket *ss = ssl_FindSocket(fd); if (!ss) { - SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetStapledOCSPResponse", + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_PeerStapledOCSPResponses", SSL_GETPID(), fd)); return NULL; } @@ -2222,6 +2235,34 @@ ssl_GetSockName(PRFileDesc *fd, PRNetAddr *name) return (PRStatus)(*ss->ops->getsockname)(ss, name); } +SECStatus +SSL_SetStapledOCSPResponses(PRFileDesc *fd, SECItemArray *responses, + PRBool takeOwnership) +{ + sslSocket *ss; + + ss = ssl_FindSocket(fd); + if (!ss) { + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetStapledOCSPResponses", + SSL_GETPID(), fd)); + return SECFailure; + } + + if (ss->certStatusArray) { + SECITEM_FreeArray(ss->certStatusArray, PR_TRUE); + ss->certStatusArray = NULL; + } + if (responses) { + if (takeOwnership) { + ss->certStatusArray = responses; + } + else { + ss->certStatusArray = SECITEM_DupArray(NULL, responses); + } + } + return (ss->certStatusArray || !responses) ? SECSuccess : SECFailure; +} + SECStatus SSL_SetSockPeerID(PRFileDesc *fd, const char *peerID) { @@ -2229,7 +2270,7 @@ SSL_SetSockPeerID(PRFileDesc *fd, const char *peerID) ss = ssl_FindSocket(fd); if (!ss) { - SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetCacheIndex", + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetSockPeerID", SSL_GETPID(), fd)); return SECFailure; } @@ -2922,6 +2963,7 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant) } ss->stepDownKeyPair = NULL; ss->dbHandle = CERT_GetDefaultCertDB(); + ss->certStatusArray = NULL; /* Provide default implementation of hooks */ ss->authCertificate = SSL_AuthCertificate; diff --git a/mozilla/security/nss/lib/util/nssutil.def b/mozilla/security/nss/lib/util/nssutil.def index 4430fe9185c..b7a94b2193a 100644 --- a/mozilla/security/nss/lib/util/nssutil.def +++ b/mozilla/security/nss/lib/util/nssutil.def @@ -264,6 +264,7 @@ NSSUTIL_QuoteSize; ;+NSSUTIL_3.14.2 { # NSS Utilities 3.14.2 release ;+ global: SECITEM_AllocArray; +SECITEM_DupArray; SECITEM_FreeArray; SECITEM_ZfreeArray; ;+ local: diff --git a/mozilla/security/nss/lib/util/secitem.c b/mozilla/security/nss/lib/util/secitem.c index 0d2312eef00..a03dd06fccf 100644 --- a/mozilla/security/nss/lib/util/secitem.c +++ b/mozilla/security/nss/lib/util/secitem.c @@ -5,7 +5,7 @@ /* * Support routines for SECItem data structure. * - * $Id: secitem.c,v 1.19 2013-02-15 17:55:42 kaie%kuix.de Exp $ + * $Id: secitem.c,v 1.20 2013-02-15 17:56:19 kaie%kuix.de Exp $ */ #include "seccomon.h" @@ -392,3 +392,28 @@ void SECITEM_ZfreeArray(SECItemArray *array, PRBool freeit) { secitem_FreeArray(array, PR_TRUE, freeit); } + +SECItemArray * +SECITEM_DupArray(PLArenaPool *arena, const SECItemArray *from) +{ + SECItemArray *result; + unsigned int i; + + if (!from || !from->items || !from->len) + return NULL; + + result = SECITEM_AllocArray(arena, NULL, from->len); + if (!result) + return NULL; + + for (i=0; ilen; ++i) { + SECStatus rv = SECITEM_CopyItem(arena, + &result->items[i], &from->items[i]); + if (rv != SECSuccess) { + SECITEM_ZfreeArray(result, PR_TRUE); + return NULL; + } + } + + return result; +} diff --git a/mozilla/security/nss/lib/util/secitem.h b/mozilla/security/nss/lib/util/secitem.h index f377bebeaff..551fbad94bc 100644 --- a/mozilla/security/nss/lib/util/secitem.h +++ b/mozilla/security/nss/lib/util/secitem.h @@ -11,7 +11,7 @@ * secitem.h - public data structures and prototypes for handling * SECItems * - * $Id: secitem.h,v 1.10 2013-02-15 17:55:42 kaie%kuix.de Exp $ + * $Id: secitem.h,v 1.11 2013-02-15 17:56:19 kaie%kuix.de Exp $ */ #include "plarena.h" @@ -93,6 +93,7 @@ PRIntn PR_CALLBACK SECITEM_HashCompare ( const void *k1, const void *k2); extern SECItemArray *SECITEM_AllocArray(PLArenaPool *arena, SECItemArray *array, unsigned int len); +extern SECItemArray *SECITEM_DupArray(PLArenaPool *arena, const SECItemArray *from); extern void SECITEM_FreeArray(SECItemArray *array, PRBool freeit); extern void SECITEM_ZfreeArray(SECItemArray *array, PRBool freeit);