| Index: net/third_party/nss/ssl/sslplatf.c
|
| diff --git a/net/third_party/nss/ssl/sslplatf.c b/net/third_party/nss/ssl/sslplatf.c
|
| deleted file mode 100644
|
| index 6f3cca64da813764f7099187b595e1c1069b4fb2..0000000000000000000000000000000000000000
|
| --- a/net/third_party/nss/ssl/sslplatf.c
|
| +++ /dev/null
|
| @@ -1,766 +0,0 @@
|
| -/*
|
| - * 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;
|
| -}
|
| -
|
| -/* Given the length of a raw DSA signature (consisting of two integers
|
| - * r and s), returns the maximum length of the DER encoding of the
|
| - * following structure:
|
| - *
|
| - * Dss-Sig-Value ::= SEQUENCE {
|
| - * r INTEGER,
|
| - * s INTEGER
|
| - * }
|
| - */
|
| -static unsigned int
|
| -ssl3_DSAMaxDerEncodedLength(unsigned int rawDsaLen)
|
| -{
|
| - /* The length of one INTEGER. */
|
| - unsigned int integerDerLen = rawDsaLen/2 + /* the integer itself */
|
| - 1 + /* additional zero byte if high bit is 1 */
|
| - SEC_ASN1LengthLength(rawDsaLen/2 + 1) + /* length */
|
| - 1; /* INTEGER tag */
|
| -
|
| - /* The length of two INTEGERs in a SEQUENCE */
|
| - return 2 * integerDerLen + /* two INTEGERs */
|
| - SEC_ASN1LengthLength(2 * integerDerLen) + /* length */
|
| - 1; /* SEQUENCE tag */
|
| -}
|
| -
|
| -SECStatus
|
| -ssl3_PlatformSignHashes(SSL3Hashes *hash, PlatformKey key, SECItem *buf,
|
| - PRBool isTLS, KeyType keyType)
|
| -{
|
| - SECStatus rv = SECFailure;
|
| - PRBool doDerDecode = PR_FALSE;
|
| - unsigned int rawDsaLen;
|
| - 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;
|
| - }
|
| -
|
| - sigAlg = cssmKey->KeyHeader.AlgorithmId;
|
| - digestAlg = CSSM_ALGID_NONE;
|
| -
|
| - switch (keyType) {
|
| - case rsaKey:
|
| - PORT_Assert(sigAlg == CSSM_ALGID_RSA);
|
| - signatureLen = (cssmKey->KeyHeader.LogicalKeySizeInBits + 7) / 8;
|
| - 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:
|
| - /* SSL3 DSA signatures are raw, not DER-encoded. CSSM gives back
|
| - * DER-encoded signatures, so they must be decoded. */
|
| - doDerDecode = (keyType == dsaKey) && !isTLS;
|
| -
|
| - /* Compute the maximum size of a DER-encoded signature: */
|
| - if (keyType == ecKey) {
|
| - PORT_Assert(sigAlg == CSSM_ALGID_ECDSA);
|
| - /* LogicalKeySizeInBits is the size of an EC public key. But an
|
| - * ECDSA signature length depends on the size of the base
|
| - * point's order. For P-256, P-384, and P-521, these two sizes
|
| - * are the same. */
|
| - rawDsaLen =
|
| - (cssmKey->KeyHeader.LogicalKeySizeInBits + 7) / 8 * 2;
|
| - } else {
|
| - /* TODO(davidben): Get the size of the subprime out of CSSM. For
|
| - * now, assume 160; Apple's implementation hardcodes it. */
|
| - PORT_Assert(sigAlg == CSSM_ALGID_DSA);
|
| - rawDsaLen = 2 * (160 / 8);
|
| - }
|
| - signatureLen = ssl3_DSAMaxDerEncodedLength(rawDsaLen);
|
| -
|
| - /* SEC_OID_UNKNOWN is used to specify the MD5/SHA1 concatenated
|
| - * hash. In that case, we use just the SHA1 part. */
|
| - 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));
|
| -
|
| - 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. */
|
| -
|
| - /* 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 (doDerDecode) {
|
| - SECItem* rawSig = DSAU_DecodeDerSigToLen(buf, rawDsaLen);
|
| - if (rawSig != NULL) {
|
| - PORT_Free(buf->data); /* discard encoded signature. */
|
| - *buf = *rawSig; /* give caller unencoded signature. */
|
| - PORT_Free(rawSig);
|
| - rv = SECSuccess;
|
| - }
|
| - } 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 */
|
|
|