2 * Platform specific crypto wrappers
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is the Netscape security libraries.
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1994-2000
22 * the Initial Developer. All Rights Reserved.
25 * Ryan Sleevi <ryan.sleevi@gmail.com>
27 * Alternatively, the contents of this file may be used under the terms of
28 * either the GNU General Public License Version 2 or later (the "GPL"), or
29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
51 #ifdef NSS_PLATFORM_CLIENT_AUTH
57 #ifdef NSS_PLATFORM_CLIENT_AUTH
59 hack_NewCertificateListFromCertList(CERTCertList
* list
)
61 CERTCertificateList
* chain
= NULL
;
62 PLArenaPool
* arena
= NULL
;
63 CERTCertListNode
* node
;
66 if (CERT_LIST_EMPTY(list
))
69 arena
= PORT_NewArena(4096);
73 for (len
= 0, node
= CERT_LIST_HEAD(list
); !CERT_LIST_END(node
, list
);
74 len
++, node
= CERT_LIST_NEXT(node
)) {
77 chain
= PORT_ArenaNew(arena
, CERTCertificateList
);
81 chain
->certs
= PORT_ArenaNewArray(arena
, SECItem
, len
);
86 for (len
= 0, node
= CERT_LIST_HEAD(list
); !CERT_LIST_END(node
, list
);
87 len
++, node
= CERT_LIST_NEXT(node
)) {
88 // Check to see if the last cert to be sent is a self-signed cert,
89 // and if so, omit it from the list of certificates. However, if
90 // there is only one cert (len == 0), include the cert, as it means
91 // the EE cert is self-signed.
92 if (len
> 0 && (len
== chain
->len
- 1) && node
->cert
->isRoot
) {
96 SECITEM_CopyItem(arena
, &chain
->certs
[len
], &node
->cert
->derCert
);
104 PORT_FreeArena(arena
, PR_FALSE
);
109 #if defined(XP_WIN32)
110 typedef SECURITY_STATUS (WINAPI
*NCryptFreeObjectFunc
)(NCRYPT_HANDLE
);
111 typedef SECURITY_STATUS (WINAPI
*NCryptSignHashFunc
)(
112 NCRYPT_KEY_HANDLE
/* hKey */,
113 VOID
* /* pPaddingInfo */,
114 PBYTE
/* pbHashValue */,
115 DWORD
/* cbHashValue */,
116 PBYTE
/* pbSignature */,
117 DWORD
/* cbSignature */,
118 DWORD
* /* pcbResult */,
119 DWORD
/* dwFlags */);
121 static PRCallOnceType cngFunctionsInitOnce
;
122 static const PRCallOnceType pristineCallOnce
;
124 static PRLibrary
*ncrypt_library
= NULL
;
125 static NCryptFreeObjectFunc pNCryptFreeObject
= NULL
;
126 static NCryptSignHashFunc pNCryptSignHash
= NULL
;
129 ssl_ShutdownCngFunctions(void *appData
, void *nssData
)
131 pNCryptSignHash
= NULL
;
132 pNCryptFreeObject
= NULL
;
133 if (ncrypt_library
) {
134 PR_UnloadLibrary(ncrypt_library
);
135 ncrypt_library
= NULL
;
138 cngFunctionsInitOnce
= pristineCallOnce
;
144 ssl_InitCngFunctions(void)
148 ncrypt_library
= PR_LoadLibrary("ncrypt.dll");
149 if (ncrypt_library
== NULL
)
152 pNCryptFreeObject
= (NCryptFreeObjectFunc
)PR_FindFunctionSymbol(
153 ncrypt_library
, "NCryptFreeObject");
154 if (pNCryptFreeObject
== NULL
)
157 pNCryptSignHash
= (NCryptSignHashFunc
)PR_FindFunctionSymbol(
158 ncrypt_library
, "NCryptSignHash");
159 if (pNCryptSignHash
== NULL
)
162 rv
= NSS_RegisterShutdown(ssl_ShutdownCngFunctions
, NULL
);
163 if (rv
!= SECSuccess
)
169 pNCryptSignHash
= NULL
;
170 pNCryptFreeObject
= NULL
;
171 if (ncrypt_library
) {
172 PR_UnloadLibrary(ncrypt_library
);
173 ncrypt_library
= NULL
;
182 if (PR_CallOnce(&cngFunctionsInitOnce
, ssl_InitCngFunctions
) != PR_SUCCESS
)
188 ssl_FreePlatformKey(PlatformKey key
)
193 if (key
->dwKeySpec
== CERT_NCRYPT_KEY_SPEC
) {
194 if (ssl_InitCng() == SECSuccess
) {
195 (*pNCryptFreeObject
)(key
->hNCryptKey
);
198 CryptReleaseContext(key
->hCryptProv
, 0);
204 ssl3_CngPlatformSignHashes(SSL3Hashes
*hash
, PlatformKey key
, SECItem
*buf
,
205 PRBool isTLS
, KeyType keyType
)
207 SECStatus rv
= SECFailure
;
208 SECURITY_STATUS ncrypt_status
;
209 PRBool doDerEncode
= PR_FALSE
;
211 DWORD signatureLen
= 0;
213 VOID
*pPaddingInfo
= NULL
;
215 /* Always encode using PKCS#1 block type. */
216 BCRYPT_PKCS1_PADDING_INFO rsaPaddingInfo
;
218 if (key
->dwKeySpec
!= CERT_NCRYPT_KEY_SPEC
) {
219 PR_SetError(SEC_ERROR_LIBRARY_FAILURE
, 0);
222 if (ssl_InitCng() != SECSuccess
) {
223 PR_SetError(SEC_ERROR_LIBRARY_FAILURE
, 0);
229 switch (hash
->hashAlg
) {
230 case SEC_OID_UNKNOWN
:
231 /* No OID/encoded DigestInfo. */
232 rsaPaddingInfo
.pszAlgId
= NULL
;
235 rsaPaddingInfo
.pszAlgId
= BCRYPT_SHA1_ALGORITHM
;
238 rsaPaddingInfo
.pszAlgId
= BCRYPT_SHA256_ALGORITHM
;
241 rsaPaddingInfo
.pszAlgId
= BCRYPT_SHA384_ALGORITHM
;
244 rsaPaddingInfo
.pszAlgId
= BCRYPT_SHA512_ALGORITHM
;
247 PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM
);
250 hashItem
.data
= hash
->u
.raw
;
251 hashItem
.len
= hash
->len
;
252 dwFlags
= BCRYPT_PAD_PKCS1
;
253 pPaddingInfo
= &rsaPaddingInfo
;
257 if (keyType
== ecKey
) {
258 doDerEncode
= PR_TRUE
;
262 if (hash
->hashAlg
== SEC_OID_UNKNOWN
) {
263 hashItem
.data
= hash
->u
.s
.sha
;
264 hashItem
.len
= sizeof(hash
->u
.s
.sha
);
266 hashItem
.data
= hash
->u
.raw
;
267 hashItem
.len
= hash
->len
;
271 PORT_SetError(SEC_ERROR_INVALID_KEY
);
274 PRINT_BUF(60, (NULL
, "hash(es) to be signed", hashItem
.data
, hashItem
.len
));
276 ncrypt_status
= (*pNCryptSignHash
)(key
->hNCryptKey
, pPaddingInfo
,
277 (PBYTE
)hashItem
.data
, hashItem
.len
,
278 NULL
, 0, &signatureLen
, dwFlags
);
279 if (FAILED(ncrypt_status
) || signatureLen
== 0) {
280 PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE
, ncrypt_status
);
284 buf
->data
= (unsigned char *)PORT_Alloc(signatureLen
);
286 goto done
; /* error code was set. */
289 ncrypt_status
= (*pNCryptSignHash
)(key
->hNCryptKey
, pPaddingInfo
,
290 (PBYTE
)hashItem
.data
, hashItem
.len
,
291 (PBYTE
)buf
->data
, signatureLen
,
292 &signatureLen
, dwFlags
);
293 if (FAILED(ncrypt_status
) || signatureLen
== 0) {
294 PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE
, ncrypt_status
);
298 buf
->len
= signatureLen
;
301 SECItem derSig
= {siBuffer
, NULL
, 0};
303 /* This also works for an ECDSA signature */
304 rv
= DSAU_EncodeDerSigWithLen(&derSig
, buf
, buf
->len
);
305 if (rv
== SECSuccess
) {
306 PORT_Free(buf
->data
); /* discard unencoded signature. */
307 *buf
= derSig
; /* give caller encoded signature. */
308 } else if (derSig
.data
) {
309 PORT_Free(derSig
.data
);
315 PRINT_BUF(60, (NULL
, "signed hashes", buf
->data
, buf
->len
));
318 if (rv
!= SECSuccess
&& buf
->data
) {
319 PORT_Free(buf
->data
);
328 ssl3_CAPIPlatformSignHashes(SSL3Hashes
*hash
, PlatformKey key
, SECItem
*buf
,
329 PRBool isTLS
, KeyType keyType
)
331 SECStatus rv
= SECFailure
;
332 PRBool doDerEncode
= PR_FALSE
;
335 DWORD signatureLen
= 0;
337 HCRYPTHASH hHash
= 0;
343 switch (hash
->hashAlg
) {
344 case SEC_OID_UNKNOWN
:
351 hashAlg
= CALG_SHA_256
;
354 hashAlg
= CALG_SHA_384
;
357 hashAlg
= CALG_SHA_512
;
360 PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM
);
367 hashAlg
= CALG_SSL3_SHAMD5
;
369 hashItem
.data
= hash
->u
.raw
;
370 hashItem
.len
= hash
->len
;
374 if (keyType
== ecKey
) {
375 doDerEncode
= PR_TRUE
;
381 hashItem
.data
= hash
->u
.s
.sha
;
382 hashItem
.len
= sizeof(hash
->u
.s
.sha
);
384 hashItem
.data
= hash
->u
.raw
;
385 hashItem
.len
= hash
->len
;
389 PORT_SetError(SEC_ERROR_INVALID_KEY
);
392 PRINT_BUF(60, (NULL
, "hash(es) to be signed", hashItem
.data
, hashItem
.len
));
394 if (!CryptCreateHash(key
->hCryptProv
, hashAlg
, 0, 0, &hHash
)) {
395 PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE
, GetLastError());
398 argLen
= sizeof(hashLen
);
399 if (!CryptGetHashParam(hHash
, HP_HASHSIZE
, (BYTE
*)&hashLen
, &argLen
, 0)) {
400 PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE
, GetLastError());
403 if (hashLen
!= hashItem
.len
) {
404 PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE
, 0);
407 if (!CryptSetHashParam(hHash
, HP_HASHVAL
, (BYTE
*)hashItem
.data
, 0)) {
408 PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE
, GetLastError());
411 if (!CryptSignHash(hHash
, key
->dwKeySpec
, NULL
, 0,
412 NULL
, &signatureLen
) || signatureLen
== 0) {
413 PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE
, GetLastError());
416 buf
->data
= (unsigned char *)PORT_Alloc(signatureLen
);
418 goto done
; /* error code was set. */
420 if (!CryptSignHash(hHash
, key
->dwKeySpec
, NULL
, 0,
421 (BYTE
*)buf
->data
, &signatureLen
)) {
422 PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE
, GetLastError());
425 buf
->len
= signatureLen
;
427 /* CryptoAPI signs in little-endian, so reverse */
428 for (i
= 0; i
< buf
->len
/ 2; ++i
) {
429 unsigned char tmp
= buf
->data
[i
];
430 buf
->data
[i
] = buf
->data
[buf
->len
- 1 - i
];
431 buf
->data
[buf
->len
- 1 - i
] = tmp
;
434 SECItem derSig
= {siBuffer
, NULL
, 0};
436 /* This also works for an ECDSA signature */
437 rv
= DSAU_EncodeDerSigWithLen(&derSig
, buf
, buf
->len
);
438 if (rv
== SECSuccess
) {
439 PORT_Free(buf
->data
); /* discard unencoded signature. */
440 *buf
= derSig
; /* give caller encoded signature. */
441 } else if (derSig
.data
) {
442 PORT_Free(derSig
.data
);
448 PRINT_BUF(60, (NULL
, "signed hashes", buf
->data
, buf
->len
));
451 CryptDestroyHash(hHash
);
452 if (rv
!= SECSuccess
&& buf
->data
) {
453 PORT_Free(buf
->data
);
460 ssl3_PlatformSignHashes(SSL3Hashes
*hash
, PlatformKey key
, SECItem
*buf
,
461 PRBool isTLS
, KeyType keyType
)
463 if (key
->dwKeySpec
== CERT_NCRYPT_KEY_SPEC
) {
464 return ssl3_CngPlatformSignHashes(hash
, key
, buf
, isTLS
, keyType
);
466 return ssl3_CAPIPlatformSignHashes(hash
, key
, buf
, isTLS
, keyType
);
469 #elif defined(XP_MACOSX)
470 #include <Security/cssm.h>
473 ssl_FreePlatformKey(PlatformKey key
)
478 #define SSL_MAX_DIGEST_INFO_PREFIX 20
480 /* ssl3_GetDigestInfoPrefix sets |out| and |out_len| to point to a buffer that
481 * contains ASN.1 data that should be prepended to a hash of the given type in
482 * order to create a DigestInfo structure that is valid for use in a PKCS #1
483 * v1.5 RSA signature. |out_len| will not be set to a value greater than
484 * SSL_MAX_DIGEST_INFO_PREFIX. */
486 ssl3_GetDigestInfoPrefix(SECOidTag hashAlg
,
487 const SSL3Opaque
** out
, unsigned int *out_len
)
489 /* These are the DER encoding of ASN.1 DigestInfo structures:
490 * DigestInfo ::= SEQUENCE {
491 * digestAlgorithm AlgorithmIdentifier,
492 * digest OCTET STRING
494 * See PKCS #1 v2.2 Section 9.2, Note 1.
496 static const unsigned char kSHA1
[] = {
497 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e,
498 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
500 static const unsigned char kSHA224
[] = {
501 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
502 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05,
505 static const unsigned char kSHA256
[] = {
506 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
507 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
510 static const unsigned char kSHA384
[] = {
511 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
512 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
515 static const unsigned char kSHA512
[] = {
516 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
517 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
522 case SEC_OID_UNKNOWN
:
527 *out_len
= sizeof(kSHA1
);
531 *out_len
= sizeof(kSHA224
);
535 *out_len
= sizeof(kSHA256
);
539 *out_len
= sizeof(kSHA384
);
543 *out_len
= sizeof(kSHA512
);
546 PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM
);
553 /* Given the length of a raw DSA signature (consisting of two integers
554 * r and s), returns the maximum length of the DER encoding of the
555 * following structure:
557 * Dss-Sig-Value ::= SEQUENCE {
563 ssl3_DSAMaxDerEncodedLength(unsigned int rawDsaLen
)
565 /* The length of one INTEGER. */
566 unsigned int integerDerLen
= rawDsaLen
/2 + /* the integer itself */
567 1 + /* additional zero byte if high bit is 1 */
568 SEC_ASN1LengthLength(rawDsaLen
/2 + 1) + /* length */
571 /* The length of two INTEGERs in a SEQUENCE */
572 return 2 * integerDerLen
+ /* two INTEGERs */
573 SEC_ASN1LengthLength(2 * integerDerLen
) + /* length */
574 1; /* SEQUENCE tag */
578 ssl3_PlatformSignHashes(SSL3Hashes
*hash
, PlatformKey key
, SECItem
*buf
,
579 PRBool isTLS
, KeyType keyType
)
581 SECStatus rv
= SECFailure
;
582 PRBool doDerDecode
= PR_FALSE
;
583 unsigned int rawDsaLen
;
584 unsigned int signatureLen
;
585 OSStatus status
= noErr
;
586 CSSM_CSP_HANDLE cspHandle
= 0;
587 const CSSM_KEY
*cssmKey
= NULL
;
588 CSSM_ALGORITHMS sigAlg
;
589 CSSM_ALGORITHMS digestAlg
;
590 const CSSM_ACCESS_CREDENTIALS
* cssmCreds
= NULL
;
593 CSSM_DATA signatureData
;
594 CSSM_CC_HANDLE cssmSignature
= 0;
595 const SSL3Opaque
* prefix
;
596 unsigned int prefixLen
;
597 SSL3Opaque prefixAndHash
[SSL_MAX_DIGEST_INFO_PREFIX
+ HASH_LENGTH_MAX
];
601 status
= SecKeyGetCSPHandle(key
, &cspHandle
);
602 if (status
!= noErr
) {
603 PORT_SetError(SEC_ERROR_INVALID_KEY
);
607 status
= SecKeyGetCSSMKey(key
, &cssmKey
);
608 if (status
!= noErr
|| !cssmKey
) {
609 PORT_SetError(SEC_ERROR_NO_KEY
);
613 sigAlg
= cssmKey
->KeyHeader
.AlgorithmId
;
614 digestAlg
= CSSM_ALGID_NONE
;
618 PORT_Assert(sigAlg
== CSSM_ALGID_RSA
);
619 signatureLen
= (cssmKey
->KeyHeader
.LogicalKeySizeInBits
+ 7) / 8;
620 if (ssl3_GetDigestInfoPrefix(hash
->hashAlg
, &prefix
, &prefixLen
) !=
624 if (prefixLen
+ hash
->len
> sizeof(prefixAndHash
)) {
625 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE
);
628 memcpy(prefixAndHash
, prefix
, prefixLen
);
629 memcpy(prefixAndHash
+ prefixLen
, hash
->u
.raw
, hash
->len
);
630 hashData
.Data
= prefixAndHash
;
631 hashData
.Length
= prefixLen
+ hash
->len
;
635 /* SSL3 DSA signatures are raw, not DER-encoded. CSSM gives back
636 * DER-encoded signatures, so they must be decoded. */
637 doDerDecode
= (keyType
== dsaKey
) && !isTLS
;
639 /* Compute the maximum size of a DER-encoded signature: */
640 if (keyType
== ecKey
) {
641 PORT_Assert(sigAlg
== CSSM_ALGID_ECDSA
);
642 /* LogicalKeySizeInBits is the size of an EC public key. But an
643 * ECDSA signature length depends on the size of the base
644 * point's order. For P-256, P-384, and P-521, these two sizes
647 (cssmKey
->KeyHeader
.LogicalKeySizeInBits
+ 7) / 8 * 2;
649 /* TODO(davidben): Get the size of the subprime out of CSSM. For
650 * now, assume 160; Apple's implementation hardcodes it. */
651 PORT_Assert(sigAlg
== CSSM_ALGID_DSA
);
652 rawDsaLen
= 2 * (160 / 8);
654 signatureLen
= ssl3_DSAMaxDerEncodedLength(rawDsaLen
);
656 /* SEC_OID_UNKNOWN is used to specify the MD5/SHA1 concatenated
657 * hash. In that case, we use just the SHA1 part. */
658 if (hash
->hashAlg
== SEC_OID_UNKNOWN
) {
659 hashData
.Data
= hash
->u
.s
.sha
;
660 hashData
.Length
= sizeof(hash
->u
.s
.sha
);
662 hashData
.Data
= hash
->u
.raw
;
663 hashData
.Length
= hash
->len
;
667 PORT_SetError(SEC_ERROR_INVALID_KEY
);
670 PRINT_BUF(60, (NULL
, "hash(es) to be signed", hashData
.Data
, hashData
.Length
));
672 if (signatureLen
== 0) {
673 PORT_SetError(SEC_ERROR_INVALID_KEY
);
677 buf
->data
= (unsigned char *)PORT_Alloc(signatureLen
);
679 goto done
; /* error code was set. */
681 /* TODO(rsleevi): Should it be kSecCredentialTypeNoUI? In Win32, at least,
682 * you can prevent the UI by setting the provider handle on the
683 * certificate to be opened with CRYPT_SILENT, but is there an equivalent?
685 status
= SecKeyGetCredentials(key
, CSSM_ACL_AUTHORIZATION_SIGN
,
686 kSecCredentialTypeDefault
, &cssmCreds
);
687 if (status
!= noErr
) {
688 PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE
, status
);
692 signatureData
.Length
= signatureLen
;
693 signatureData
.Data
= (uint8
*)buf
->data
;
695 cssmRv
= CSSM_CSP_CreateSignatureContext(cspHandle
, sigAlg
, cssmCreds
,
696 cssmKey
, &cssmSignature
);
698 PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE
, cssmRv
);
702 /* See "Apple Cryptographic Service Provider Functional Specification" */
703 if (cssmKey
->KeyHeader
.AlgorithmId
== CSSM_ALGID_RSA
) {
704 /* To set RSA blinding for RSA keys */
705 CSSM_CONTEXT_ATTRIBUTE blindingAttr
;
706 blindingAttr
.AttributeType
= CSSM_ATTRIBUTE_RSA_BLINDING
;
707 blindingAttr
.AttributeLength
= sizeof(uint32
);
708 blindingAttr
.Attribute
.Uint32
= 1;
709 cssmRv
= CSSM_UpdateContextAttributes(cssmSignature
, 1, &blindingAttr
);
711 PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE
, cssmRv
);
716 cssmRv
= CSSM_SignData(cssmSignature
, &hashData
, 1, digestAlg
,
719 PR_SetError(SSL_ERROR_SIGN_HASHES_FAILURE
, cssmRv
);
722 buf
->len
= signatureData
.Length
;
725 SECItem
* rawSig
= DSAU_DecodeDerSigToLen(buf
, rawDsaLen
);
726 if (rawSig
!= NULL
) {
727 PORT_Free(buf
->data
); /* discard encoded signature. */
728 *buf
= *rawSig
; /* give caller unencoded signature. */
736 PRINT_BUF(60, (NULL
, "signed hashes", buf
->data
, buf
->len
));
738 /* cspHandle, cssmKey, and cssmCreds are owned by the SecKeyRef and
739 * should not be freed. When the PlatformKey is freed, they will be
743 CSSM_DeleteContext(cssmSignature
);
745 if (rv
!= SECSuccess
&& buf
->data
) {
746 PORT_Free(buf
->data
);
753 ssl_FreePlatformKey(PlatformKey key
)
758 ssl3_PlatformSignHashes(SSL3Hashes
*hash
, PlatformKey key
, SECItem
*buf
,
759 PRBool isTLS
, KeyType keyType
)
761 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR
);
766 #endif /* NSS_PLATFORM_CLIENT_AUTH */