diff options
Diffstat (limited to 'chromium/net/third_party/nss/ssl/sslplatf.c')
-rw-r--r-- | chromium/net/third_party/nss/ssl/sslplatf.c | 732 |
1 files changed, 732 insertions, 0 deletions
diff --git a/chromium/net/third_party/nss/ssl/sslplatf.c b/chromium/net/third_party/nss/ssl/sslplatf.c new file mode 100644 index 00000000000..fee702191a7 --- /dev/null +++ b/chromium/net/third_party/nss/ssl/sslplatf.c @@ -0,0 +1,732 @@ +/* + * Platform specific crypto wrappers + * + * ***** 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): + * Ryan Sleevi <ryan.sleevi@gmail.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 ***** */ +/* $Id$ */ +#include "certt.h" +#include "cryptohi.h" +#include "keythi.h" +#include "nss.h" +#include "secitem.h" +#include "ssl.h" +#include "sslimpl.h" +#include "prerror.h" +#include "prinit.h" + +#ifdef NSS_PLATFORM_CLIENT_AUTH +#ifdef XP_WIN32 +#include <NCrypt.h> +#endif +#endif + +#ifdef NSS_PLATFORM_CLIENT_AUTH +CERTCertificateList* +hack_NewCertificateListFromCertList(CERTCertList* list) +{ + CERTCertificateList * chain = NULL; + PLArenaPool * arena = NULL; + CERTCertListNode * node; + int len; + + if (CERT_LIST_EMPTY(list)) + goto loser; + + arena = PORT_NewArena(4096); + if (arena == NULL) + goto loser; + + for (len = 0, node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list); + len++, node = CERT_LIST_NEXT(node)) { + } + + chain = PORT_ArenaNew(arena, CERTCertificateList); + if (chain == NULL) + goto loser; + + chain->certs = PORT_ArenaNewArray(arena, SECItem, len); + if (!chain->certs) + goto loser; + chain->len = len; + + for (len = 0, node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list); + len++, node = CERT_LIST_NEXT(node)) { + // Check to see if the last cert to be sent is a self-signed cert, + // and if so, omit it from the list of certificates. However, if + // there is only one cert (len == 0), include the cert, as it means + // the EE cert is self-signed. + if (len > 0 && (len == chain->len - 1) && node->cert->isRoot) { + chain->len = len; + break; + } + SECITEM_CopyItem(arena, &chain->certs[len], &node->cert->derCert); + } + + chain->arena = arena; + return chain; + +loser: + if (arena) { + PORT_FreeArena(arena, PR_FALSE); + } + return NULL; +} + +#if defined(XP_WIN32) +typedef SECURITY_STATUS (WINAPI *NCryptFreeObjectFunc)(NCRYPT_HANDLE); +typedef SECURITY_STATUS (WINAPI *NCryptSignHashFunc)( + NCRYPT_KEY_HANDLE /* hKey */, + VOID* /* pPaddingInfo */, + PBYTE /* pbHashValue */, + DWORD /* cbHashValue */, + PBYTE /* pbSignature */, + DWORD /* cbSignature */, + DWORD* /* pcbResult */, + DWORD /* dwFlags */); + +static PRCallOnceType cngFunctionsInitOnce; +static const PRCallOnceType pristineCallOnce; + +static PRLibrary *ncrypt_library = NULL; +static NCryptFreeObjectFunc pNCryptFreeObject = NULL; +static NCryptSignHashFunc pNCryptSignHash = NULL; + +static SECStatus +ssl_ShutdownCngFunctions(void *appData, void *nssData) +{ + pNCryptSignHash = NULL; + pNCryptFreeObject = NULL; + if (ncrypt_library) { + PR_UnloadLibrary(ncrypt_library); + ncrypt_library = NULL; + } + + cngFunctionsInitOnce = pristineCallOnce; + + return SECSuccess; +} + +static PRStatus +ssl_InitCngFunctions(void) +{ + SECStatus rv; + + ncrypt_library = PR_LoadLibrary("ncrypt.dll"); + if (ncrypt_library == NULL) + goto loser; + + pNCryptFreeObject = (NCryptFreeObjectFunc)PR_FindFunctionSymbol( + ncrypt_library, "NCryptFreeObject"); + if (pNCryptFreeObject == NULL) + goto loser; + + pNCryptSignHash = (NCryptSignHashFunc)PR_FindFunctionSymbol( + ncrypt_library, "NCryptSignHash"); + if (pNCryptSignHash == NULL) + goto loser; + + rv = NSS_RegisterShutdown(ssl_ShutdownCngFunctions, NULL); + if (rv != SECSuccess) + goto loser; + + return PR_SUCCESS; + +loser: + pNCryptSignHash = NULL; + pNCryptFreeObject = NULL; + if (ncrypt_library) { + PR_UnloadLibrary(ncrypt_library); + ncrypt_library = NULL; + } + + return PR_FAILURE; +} + +static SECStatus +ssl_InitCng(void) +{ + if (PR_CallOnce(&cngFunctionsInitOnce, ssl_InitCngFunctions) != PR_SUCCESS) + return SECFailure; + return SECSuccess; +} + +void +ssl_FreePlatformKey(PlatformKey key) +{ + if (!key) + return; + + if (key->dwKeySpec == CERT_NCRYPT_KEY_SPEC) { + if (ssl_InitCng() == SECSuccess) { + (*pNCryptFreeObject)(key->hNCryptKey); + } + } else { + CryptReleaseContext(key->hCryptProv, 0); + } + PORT_Free(key); +} + +static SECStatus +ssl3_CngPlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, + PRBool isTLS, KeyType keyType) +{ + SECStatus rv = SECFailure; + SECURITY_STATUS ncrypt_status; + PRBool doDerEncode = PR_FALSE; + SECItem hashItem; + DWORD signatureLen = 0; + DWORD dwFlags = 0; + VOID *pPaddingInfo = NULL; + + /* Always encode using PKCS#1 block type. */ + BCRYPT_PKCS1_PADDING_INFO rsaPaddingInfo; + + if (key->dwKeySpec != CERT_NCRYPT_KEY_SPEC) { + PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0); + return SECFailure; + } + if (ssl_InitCng() != SECSuccess) { + PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0); + return SECFailure; + } + + switch (keyType) { + case rsaKey: + switch (hash->hashAlg) { + case SEC_OID_UNKNOWN: + /* No OID/encoded DigestInfo. */ + rsaPaddingInfo.pszAlgId = NULL; + break; + case SEC_OID_SHA1: + rsaPaddingInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM; + break; + case SEC_OID_SHA256: + rsaPaddingInfo.pszAlgId = BCRYPT_SHA256_ALGORITHM; + break; + case SEC_OID_SHA384: + rsaPaddingInfo.pszAlgId = BCRYPT_SHA384_ALGORITHM; + break; + case SEC_OID_SHA512: + rsaPaddingInfo.pszAlgId = BCRYPT_SHA512_ALGORITHM; + break; + default: + PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM); + return SECFailure; + } + hashItem.data = hash->u.raw; + hashItem.len = hash->len; + dwFlags = BCRYPT_PAD_PKCS1; + pPaddingInfo = &rsaPaddingInfo; + break; + case dsaKey: + case ecKey: + if (keyType == ecKey) { + doDerEncode = PR_TRUE; + } else { + doDerEncode = isTLS; + } + if (hash->hashAlg == SEC_OID_UNKNOWN) { + hashItem.data = hash->u.s.sha; + hashItem.len = sizeof(hash->u.s.sha); + } else { + hashItem.data = hash->u.raw; + hashItem.len = hash->len; + } + break; + default: + PORT_SetError(SEC_ERROR_INVALID_KEY); + goto done; + } + PRINT_BUF(60, (NULL, "hash(es) to be signed", hashItem.data, hashItem.len)); + + ncrypt_status = (*pNCryptSignHash)(key->hNCryptKey, pPaddingInfo, + (PBYTE)hashItem.data, hashItem.len, + NULL, 0, &signatureLen, dwFlags); + if (FAILED(ncrypt_status) || signatureLen == 0) { + PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, ncrypt_status); + goto done; + } + + buf->data = (unsigned char *)PORT_Alloc(signatureLen); + if (!buf->data) { + goto done; /* error code was set. */ + } + + ncrypt_status = (*pNCryptSignHash)(key->hNCryptKey, pPaddingInfo, + (PBYTE)hashItem.data, hashItem.len, + (PBYTE)buf->data, signatureLen, + &signatureLen, dwFlags); + if (FAILED(ncrypt_status) || signatureLen == 0) { + PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, ncrypt_status); + goto done; + } + + buf->len = signatureLen; + + if (doDerEncode) { + SECItem derSig = {siBuffer, NULL, 0}; + + /* This also works for an ECDSA signature */ + rv = DSAU_EncodeDerSigWithLen(&derSig, buf, buf->len); + if (rv == SECSuccess) { + PORT_Free(buf->data); /* discard unencoded signature. */ + *buf = derSig; /* give caller encoded signature. */ + } else if (derSig.data) { + PORT_Free(derSig.data); + } + } else { + rv = SECSuccess; + } + + PRINT_BUF(60, (NULL, "signed hashes", buf->data, buf->len)); + +done: + if (rv != SECSuccess && buf->data) { + PORT_Free(buf->data); + buf->data = NULL; + buf->len = 0; + } + + return rv; +} + +static SECStatus +ssl3_CAPIPlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, + PRBool isTLS, KeyType keyType) +{ + SECStatus rv = SECFailure; + PRBool doDerEncode = PR_FALSE; + SECItem hashItem; + DWORD argLen = 0; + DWORD signatureLen = 0; + ALG_ID hashAlg = 0; + HCRYPTHASH hHash = 0; + DWORD hashLen = 0; + unsigned int i = 0; + + buf->data = NULL; + + switch (hash->hashAlg) { + case SEC_OID_UNKNOWN: + hashAlg = 0; + break; + case SEC_OID_SHA1: + hashAlg = CALG_SHA1; + break; + case SEC_OID_SHA256: + hashAlg = CALG_SHA_256; + break; + case SEC_OID_SHA384: + hashAlg = CALG_SHA_384; + break; + case SEC_OID_SHA512: + hashAlg = CALG_SHA_512; + break; + default: + PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM); + return SECFailure; + } + + switch (keyType) { + case rsaKey: + if (hashAlg == 0) { + hashAlg = CALG_SSL3_SHAMD5; + } + hashItem.data = hash->u.raw; + hashItem.len = hash->len; + break; + case dsaKey: + case ecKey: + if (keyType == ecKey) { + doDerEncode = PR_TRUE; + } else { + doDerEncode = isTLS; + } + if (hashAlg == 0) { + hashAlg = CALG_SHA1; + hashItem.data = hash->u.s.sha; + hashItem.len = sizeof(hash->u.s.sha); + } else { + hashItem.data = hash->u.raw; + hashItem.len = hash->len; + } + break; + default: + PORT_SetError(SEC_ERROR_INVALID_KEY); + goto done; + } + PRINT_BUF(60, (NULL, "hash(es) to be signed", hashItem.data, hashItem.len)); + + if (!CryptCreateHash(key->hCryptProv, hashAlg, 0, 0, &hHash)) { + PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, GetLastError()); + goto done; + } + argLen = sizeof(hashLen); + if (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&hashLen, &argLen, 0)) { + PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, GetLastError()); + goto done; + } + if (hashLen != hashItem.len) { + PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, 0); + goto done; + } + if (!CryptSetHashParam(hHash, HP_HASHVAL, (BYTE*)hashItem.data, 0)) { + PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, GetLastError()); + goto done; + } + if (!CryptSignHash(hHash, key->dwKeySpec, NULL, 0, + NULL, &signatureLen) || signatureLen == 0) { + PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, GetLastError()); + goto done; + } + buf->data = (unsigned char *)PORT_Alloc(signatureLen); + if (!buf->data) + goto done; /* error code was set. */ + + if (!CryptSignHash(hHash, key->dwKeySpec, NULL, 0, + (BYTE*)buf->data, &signatureLen)) { + PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, GetLastError()); + goto done; + } + buf->len = signatureLen; + + /* CryptoAPI signs in little-endian, so reverse */ + for (i = 0; i < buf->len / 2; ++i) { + unsigned char tmp = buf->data[i]; + buf->data[i] = buf->data[buf->len - 1 - i]; + buf->data[buf->len - 1 - i] = tmp; + } + if (doDerEncode) { + SECItem derSig = {siBuffer, NULL, 0}; + + /* This also works for an ECDSA signature */ + rv = DSAU_EncodeDerSigWithLen(&derSig, buf, buf->len); + if (rv == SECSuccess) { + PORT_Free(buf->data); /* discard unencoded signature. */ + *buf = derSig; /* give caller encoded signature. */ + } else if (derSig.data) { + PORT_Free(derSig.data); + } + } else { + rv = SECSuccess; + } + + PRINT_BUF(60, (NULL, "signed hashes", buf->data, buf->len)); +done: + if (hHash) + CryptDestroyHash(hHash); + if (rv != SECSuccess && buf->data) { + PORT_Free(buf->data); + buf->data = NULL; + } + return rv; +} + +SECStatus +ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, + PRBool isTLS, KeyType keyType) +{ + if (key->dwKeySpec == CERT_NCRYPT_KEY_SPEC) { + return ssl3_CngPlatformSignHashes(hash, key, buf, isTLS, keyType); + } + return ssl3_CAPIPlatformSignHashes(hash, key, buf, isTLS, keyType); +} + +#elif defined(XP_MACOSX) +#include <Security/cssm.h> + +void +ssl_FreePlatformKey(PlatformKey key) +{ + CFRelease(key); +} + +#define SSL_MAX_DIGEST_INFO_PREFIX 20 + +/* ssl3_GetDigestInfoPrefix sets |out| and |out_len| to point to a buffer that + * contains ASN.1 data that should be prepended to a hash of the given type in + * order to create a DigestInfo structure that is valid for use in a PKCS #1 + * v1.5 RSA signature. |out_len| will not be set to a value greater than + * SSL_MAX_DIGEST_INFO_PREFIX. */ +static SECStatus +ssl3_GetDigestInfoPrefix(SECOidTag hashAlg, + const SSL3Opaque** out, unsigned int *out_len) +{ + /* These are the DER encoding of ASN.1 DigestInfo structures: + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + * See PKCS #1 v2.2 Section 9.2, Note 1. + */ + static const unsigned char kSHA1[] = { + 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, + 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 + }; + static const unsigned char kSHA224[] = { + 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, + 0x00, 0x04, 0x1c + }; + static const unsigned char kSHA256[] = { + 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, + 0x00, 0x04, 0x20 + }; + static const unsigned char kSHA384[] = { + 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, + 0x00, 0x04, 0x30 + }; + static const unsigned char kSHA512[] = { + 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, + 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, + 0x00, 0x04, 0x40 + }; + + switch (hashAlg) { + case SEC_OID_UNKNOWN: + *out_len = 0; + break; + case SEC_OID_SHA1: + *out = kSHA1; + *out_len = sizeof(kSHA1); + break; + case SEC_OID_SHA224: + *out = kSHA224; + *out_len = sizeof(kSHA224); + break; + case SEC_OID_SHA256: + *out = kSHA256; + *out_len = sizeof(kSHA256); + break; + case SEC_OID_SHA384: + *out = kSHA384; + *out_len = sizeof(kSHA384); + break; + case SEC_OID_SHA512: + *out = kSHA512; + *out_len = sizeof(kSHA512); + break; + default: + PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM); + return SECFailure; + } + + return SECSuccess; +} + +SECStatus +ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, + PRBool isTLS, KeyType keyType) +{ + SECStatus rv = SECFailure; + PRBool doDerEncode = PR_FALSE; + unsigned int signatureLen; + OSStatus status = noErr; + CSSM_CSP_HANDLE cspHandle = 0; + const CSSM_KEY *cssmKey = NULL; + CSSM_ALGORITHMS sigAlg; + CSSM_ALGORITHMS digestAlg; + const CSSM_ACCESS_CREDENTIALS * cssmCreds = NULL; + CSSM_RETURN cssmRv; + CSSM_DATA hashData; + CSSM_DATA signatureData; + CSSM_CC_HANDLE cssmSignature = 0; + const SSL3Opaque* prefix; + unsigned int prefixLen; + SSL3Opaque prefixAndHash[SSL_MAX_DIGEST_INFO_PREFIX + HASH_LENGTH_MAX]; + + buf->data = NULL; + + status = SecKeyGetCSPHandle(key, &cspHandle); + if (status != noErr) { + PORT_SetError(SEC_ERROR_INVALID_KEY); + goto done; + } + + status = SecKeyGetCSSMKey(key, &cssmKey); + if (status != noErr || !cssmKey) { + PORT_SetError(SEC_ERROR_NO_KEY); + goto done; + } + + /* SecKeyGetBlockSize wasn't addeded until OS X 10.6 - but the + * needed information is readily available on the key itself. + */ + signatureLen = (cssmKey->KeyHeader.LogicalKeySizeInBits + 7) / 8; + + if (signatureLen == 0) { + PORT_SetError(SEC_ERROR_INVALID_KEY); + goto done; + } + + buf->data = (unsigned char *)PORT_Alloc(signatureLen); + if (!buf->data) + goto done; /* error code was set. */ + + sigAlg = cssmKey->KeyHeader.AlgorithmId; + digestAlg = CSSM_ALGID_NONE; + + switch (keyType) { + case rsaKey: + PORT_Assert(sigAlg == CSSM_ALGID_RSA); + if (ssl3_GetDigestInfoPrefix(hash->hashAlg, &prefix, &prefixLen) != + SECSuccess) { + goto done; + } + if (prefixLen + hash->len > sizeof(prefixAndHash)) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + goto done; + } + memcpy(prefixAndHash, prefix, prefixLen); + memcpy(prefixAndHash + prefixLen, hash->u.raw, hash->len); + hashData.Data = prefixAndHash; + hashData.Length = prefixLen + hash->len; + break; + case dsaKey: + case ecKey: + if (keyType == ecKey) { + PORT_Assert(sigAlg == CSSM_ALGID_ECDSA); + doDerEncode = PR_TRUE; + } else { + PORT_Assert(sigAlg == CSSM_ALGID_DSA); + doDerEncode = isTLS; + } + if (hash->hashAlg == SEC_OID_UNKNOWN) { + hashData.Data = hash->u.s.sha; + hashData.Length = sizeof(hash->u.s.sha); + } else { + hashData.Data = hash->u.raw; + hashData.Length = hash->len; + } + break; + default: + PORT_SetError(SEC_ERROR_INVALID_KEY); + goto done; + } + PRINT_BUF(60, (NULL, "hash(es) to be signed", hashData.Data, hashData.Length)); + + /* TODO(rsleevi): Should it be kSecCredentialTypeNoUI? In Win32, at least, + * you can prevent the UI by setting the provider handle on the + * certificate to be opened with CRYPT_SILENT, but is there an equivalent? + */ + status = SecKeyGetCredentials(key, CSSM_ACL_AUTHORIZATION_SIGN, + kSecCredentialTypeDefault, &cssmCreds); + if (status != noErr) { + PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, status); + goto done; + } + + signatureData.Length = signatureLen; + signatureData.Data = (uint8*)buf->data; + + cssmRv = CSSM_CSP_CreateSignatureContext(cspHandle, sigAlg, cssmCreds, + cssmKey, &cssmSignature); + if (cssmRv) { + PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, cssmRv); + goto done; + } + + /* See "Apple Cryptographic Service Provider Functional Specification" */ + if (cssmKey->KeyHeader.AlgorithmId == CSSM_ALGID_RSA) { + /* To set RSA blinding for RSA keys */ + CSSM_CONTEXT_ATTRIBUTE blindingAttr; + blindingAttr.AttributeType = CSSM_ATTRIBUTE_RSA_BLINDING; + blindingAttr.AttributeLength = sizeof(uint32); + blindingAttr.Attribute.Uint32 = 1; + cssmRv = CSSM_UpdateContextAttributes(cssmSignature, 1, &blindingAttr); + if (cssmRv) { + PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, cssmRv); + goto done; + } + } + + cssmRv = CSSM_SignData(cssmSignature, &hashData, 1, digestAlg, + &signatureData); + if (cssmRv) { + PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE, cssmRv); + goto done; + } + buf->len = signatureData.Length; + + if (doDerEncode) { + SECItem derSig = {siBuffer, NULL, 0}; + + /* This also works for an ECDSA signature */ + rv = DSAU_EncodeDerSigWithLen(&derSig, buf, buf->len); + if (rv == SECSuccess) { + PORT_Free(buf->data); /* discard unencoded signature. */ + *buf = derSig; /* give caller encoded signature. */ + } else if (derSig.data) { + PORT_Free(derSig.data); + } + } else { + rv = SECSuccess; + } + + PRINT_BUF(60, (NULL, "signed hashes", buf->data, buf->len)); +done: + /* cspHandle, cssmKey, and cssmCreds are owned by the SecKeyRef and + * should not be freed. When the PlatformKey is freed, they will be + * released. + */ + if (cssmSignature) + CSSM_DeleteContext(cssmSignature); + + if (rv != SECSuccess && buf->data) { + PORT_Free(buf->data); + buf->data = NULL; + } + return rv; +} +#else +void +ssl_FreePlatformKey(PlatformKey key) +{ +} + +SECStatus +ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf, + PRBool isTLS, KeyType keyType) +{ + PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); + return SECFailure; +} +#endif + +#endif /* NSS_PLATFORM_CLIENT_AUTH */ |