1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
* The contents of this file are subject to the Mozilla Public License Version
5
* 1.1 (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
7
* http://www.mozilla.org/MPL/
9
* Software distributed under the License is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
* for the specific language governing rights and limitations under the
14
* The Original Code is the Netscape security libraries.
16
* The Initial Developer of the Original Code is
17
* Netscape Communications Corporation.
18
* Portions created by the Initial Developer are Copyright (C) 1994-2000
19
* the Initial Developer. All Rights Reserved.
20
* Portions created by Red Hat, Inc, are Copyright (C) 2005
23
* Bob Relyea (rrelyea@redhat.com)
25
* Alternatively, the contents of this file may be used under the terms of
26
* either the GNU General Public License Version 2 or later (the "GPL"), or
27
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28
* in which case the provisions of the GPL or the LGPL are applicable instead
29
* of those above. If you wish to allow use of your version of this file only
30
* under the terms of either the GPL or the LGPL, and not to allow others to
31
* use your version of this file under the terms of the MPL, indicate your
32
* decision by deleting the provisions above and replace them with the notice
33
* and other provisions required by the GPL or the LGPL. If you do not delete
34
* the provisions above, a recipient may use your version of this file under
35
* the terms of any one of the MPL, the GPL or the LGPL.
37
* ***** END LICENSE BLOCK ***** */
39
static const char CVS_ID[] = "@(#) $RCSfile: cobject.c,v $ $Revision: 1.4 $ $Date: 2005/11/16 01:17:25 $";
48
* This file implements the NSSCKMDObject object for the
49
* "nss to capi objects" cryptoki module.
52
const CK_ATTRIBUTE_TYPE certAttrs[] = {
64
const PRUint32 certAttrsCount = NSS_CKCAPI_ARRAY_SIZE(certAttrs);
66
/* private keys, for now only support RSA */
67
const CK_ATTRIBUTE_TYPE privKeyAttrs[] = {
84
CKA_NEVER_EXTRACTABLE,
88
const PRUint32 privKeyAttrsCount = NSS_CKCAPI_ARRAY_SIZE(privKeyAttrs);
90
/* public keys, for now only support RSA */
91
const CK_ATTRIBUTE_TYPE pubKeyAttrs[] = {
108
const PRUint32 pubKeyAttrsCount = NSS_CKCAPI_ARRAY_SIZE(pubKeyAttrs);
109
static const CK_BBOOL ck_true = CK_TRUE;
110
static const CK_BBOOL ck_false = CK_FALSE;
111
static const CK_CERTIFICATE_TYPE ckc_x509 = CKC_X_509;
112
static const CK_KEY_TYPE ckk_rsa = CKK_RSA;
113
static const CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE;
114
static const CK_OBJECT_CLASS cko_private_key = CKO_PRIVATE_KEY;
115
static const CK_OBJECT_CLASS cko_public_key = CKO_PUBLIC_KEY;
116
static const NSSItem ckcapi_trueItem = {
117
(void *)&ck_true, (PRUint32)sizeof(CK_BBOOL) };
118
static const NSSItem ckcapi_falseItem = {
119
(void *)&ck_false, (PRUint32)sizeof(CK_BBOOL) };
120
static const NSSItem ckcapi_x509Item = {
121
(void *)&ckc_x509, (PRUint32)sizeof(CKC_X_509) };
122
static const NSSItem ckcapi_rsaItem = {
123
(void *)&ckk_rsa, (PRUint32)sizeof(CK_KEY_TYPE) };
124
static const NSSItem ckcapi_certClassItem = {
125
(void *)&cko_certificate, (PRUint32)sizeof(CK_OBJECT_CLASS) };
126
static const NSSItem ckcapi_privKeyClassItem = {
127
(void *)&cko_private_key, (PRUint32)sizeof(CK_OBJECT_CLASS) };
128
static const NSSItem ckcapi_pubKeyClassItem = {
129
(void *)&cko_public_key, (PRUint32)sizeof(CK_OBJECT_CLASS) };
130
static const NSSItem ckcapi_emptyItem = {
131
(void *)&ck_true, 0};
134
* these are utilities. The chould be moved to a new utilities file.
138
* unwrap a single DER value
149
unsigned char *start = src;
150
unsigned char *end = src+size;
151
unsigned int len = 0;
153
/* initialize error condition return values */
162
src ++ ; /* skip the tag -- should check it against an expected value! */
163
len = (unsigned) *src++;
165
int count = len & 0x7f;
168
if (count+2 > size) {
171
while (count-- > 0) {
172
len = (len << 8) | (unsigned) *src++;
175
if (len + (src-start) > (unsigned int)size) {
187
* convert a PKCS #11 bytestrin into a CK_ULONG, the byte stream must be
188
* less than sizeof (CK_ULONG).
198
unsigned long count = data->size;
199
unsigned char *dataPtr = data->data;
200
unsigned long size = 0;
206
value = value + *dataPtr++;
211
if (size > sizeof(CK_ULONG)) {
212
*pError = CKR_ATTRIBUTE_VALUE_INVALID;
218
* convert a CK_ULONG to a bytestream. Data is stored in the buffer 'buf'
219
* and must be at least CK_ULONG. Caller must provide buf.
226
unsigned char *dataPtr,
230
unsigned long count = 0;
232
#define SHIFT ((sizeof(CK_ULONG)-1)*8)
237
data->data = dataPtr;
238
for (i=0; i < sizeof(CK_ULONG); i++) {
239
unsigned char digit = (unsigned char)((value >> SHIFT) & 0xff);
243
/* drop leading zero bytes */
244
if (first && (0 == digit)) {
255
* get an attribute from a template. Value is returned in NSS item.
256
* data for the item is owned by the template.
259
nss_ckcapi_GetAttribute
261
CK_ATTRIBUTE_TYPE type,
262
CK_ATTRIBUTE *template,
263
CK_ULONG templateSize,
269
for (i=0; i < templateSize; i++) {
270
if (template[i].type == type) {
271
item->data = template[i].pValue;
272
item->size = template[i].ulValueLen;
276
return CKR_TEMPLATE_INCOMPLETE;
280
* get an attribute which is type CK_ULONG.
283
nss_ckcapi_GetULongAttribute
285
CK_ATTRIBUTE_TYPE type,
286
CK_ATTRIBUTE *template,
287
CK_ULONG templateSize,
293
*pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item);
294
if (CKR_OK != *pError) {
297
if (item.size != sizeof(CK_ULONG)) {
298
*pError = CKR_ATTRIBUTE_VALUE_INVALID;
301
return *(CK_ULONG *)item.data;
305
* get an attribute which is type CK_BBOOL.
308
nss_ckcapi_GetBoolAttribute
310
CK_ATTRIBUTE_TYPE type,
311
CK_ATTRIBUTE *template,
312
CK_ULONG templateSize,
318
*pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item);
319
if (CKR_OK != *pError) {
322
if (item.size != sizeof(CK_BBOOL)) {
323
*pError = CKR_ATTRIBUTE_VALUE_INVALID;
326
return *(CK_BBOOL *)item.data;
330
* get an attribute which is type CK_BBOOL.
333
nss_ckcapi_GetStringAttribute
335
CK_ATTRIBUTE_TYPE type,
336
CK_ATTRIBUTE *template,
337
CK_ULONG templateSize,
344
/* get the attribute */
345
*pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item);
346
if (CKR_OK != *pError) {
349
/* make sure it is null terminated */
350
str = nss_ZNEWARRAY(NULL, char, item.size+1);
351
if ((char *)NULL == str) {
352
*pError = CKR_HOST_MEMORY;
356
nsslibc_memcpy(str, item.data, item.size);
363
* Return the size in bytes of a wide string
373
if ((LPWSTR)NULL == wide) {
376
size = wcslen(wide)+1;
381
* Covert a Unicode wide character string to a UTF8 string
384
nss_ckcapi_WideToUTF8
393
if ((LPWSTR)NULL == wide) {
397
len = nss_ckcapi_WideSize(wide);
399
size = WideCharToMultiByte(CP_UTF8, 0, wide, len, NULL, 0, NULL, 0);
403
buf = nss_ZNEWARRAY(NULL, char, size);
404
size = WideCharToMultiByte(CP_UTF8, 0, wide, len, buf, size, NULL, 0);
413
* Return a Wide String duplicated with nss allocated memory.
421
DWORD len = nss_ckcapi_WideSize(wide);
424
if ((LPWSTR)NULL == wide) {
428
len = nss_ckcapi_WideSize(wide);
430
buf = (LPWSTR) nss_ZNEWARRAY(NULL, char, len);
431
if ((LPWSTR) NULL == buf) {
434
nsslibc_memcpy(buf, wide, len);
439
* Covert a UTF8 string to Unicode wide character
442
nss_ckcapi_UTF8ToWide
448
DWORD len = strlen(buf)+1;
451
if ((char *)NULL == buf) {
452
return (LPWSTR) NULL;
457
size = MultiByteToWideChar(CP_UTF8, 0, buf, len, NULL, 0);
459
return (LPWSTR) NULL;
461
wide = nss_ZNEWARRAY(NULL, WCHAR, size);
462
size = MultiByteToWideChar(CP_UTF8, 0, buf, len, wide, size);
465
return (LPWSTR) NULL;
472
* keep all the knowlege of how the internalObject is laid out in this function
474
* nss_ckcapi_FetchKeyContainer
476
* fetches the Provider container and info as well as a key handle for a
477
* private key. If something other than a private key is passed in,
478
* this function fails with CKR_KEY_TYPE_INCONSISTENT
481
nss_ckcapi_FetchKeyContainer
483
ckcapiInternalObject *iKey,
489
ckcapiCertObject *co;
495
switch (iKey->type) {
498
/* can't have raw private keys */
499
return CKR_KEY_TYPE_INCONSISTENT;
501
if (iKey->objClass != CKO_PRIVATE_KEY) {
502
/* Only private keys have private key provider handles */
503
return CKR_KEY_TYPE_INCONSISTENT;
507
/* OK, get the Provider */
508
rc = CryptAcquireCertificatePrivateKey(co->certContext,
509
CRYPT_ACQUIRE_CACHE_FLAG|CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, hProv,
516
if (iKey->objClass != CKO_PRIVATE_KEY) {
517
/* Only private keys have private key provider handles */
518
return CKR_KEY_TYPE_INCONSISTENT;
522
/* OK, get the Provider */
523
if (0 == ko->hProv) {
524
rc = CryptAcquireContext(hProv,
527
ko->provInfo.dwProvType , 0);
534
*keySpec = ko->provInfo.dwKeySpec;
538
/* and get the crypto handle */
539
rc = CryptGetUserKey(*hProv, *keySpec, hKey);
545
/* map the microsoft error before leaving */
546
msError = GetLastError();
548
case ERROR_INVALID_HANDLE:
549
case ERROR_INVALID_PARAMETER:
552
case NTE_BAD_PUBLIC_KEY:
554
case NTE_KEYSET_NOT_DEF:
555
return CKR_KEY_TYPE_INCONSISTENT;
557
case NTE_KEYSET_ENTRY_BAD:
558
return CKR_DEVICE_ERROR;
560
return CKR_GENERAL_ERROR;
565
* take a DER PUBLIC Key block and return the modulus and exponent
568
ckcapi_CertPopulateModulusExponent
570
ckcapiInternalObject *io
573
ckcapiKeyParams *kp = &io->u.cert.key;
574
PCCERT_CONTEXT certContext = io->u.cert.certContext;
575
char *pkData = certContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData;
576
CK_ULONG size= certContext->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData;
580
/* find the start of the modulus -- this will not give good results if
581
* the key isn't an rsa key! */
582
ptr = nss_ckcapi_DERUnwrap(pkData, size, &newSize, NULL);
583
kp->modulus.data = nss_ckcapi_DERUnwrap(ptr, newSize,
584
&kp->modulus.size, &newptr);
585
/* changed from signed to unsigned int */
586
if (0 == *(char *)kp->modulus.data) {
587
kp->modulus.data = ((char *)kp->modulus.data)+1;
588
kp->modulus.size = kp->modulus.size - 1;
590
/* changed from signed to unsigned int */
591
kp->exponent.data = nss_ckcapi_DERUnwrap(newptr, (newptr-ptr)+newSize,
592
&kp->exponent.size, NULL);
593
if (0 == *(char *)kp->exponent.data) {
594
kp->exponent.data = ((char *)kp->exponent.data)+1;
595
kp->exponent.size = kp->exponent.size - 1;
600
typedef struct _CAPI_RSA_KEY_BLOB {
601
PUBLICKEYSTRUC header;
606
#define CAPI_MODULUS_OFFSET(modSize) 0
607
#define CAPI_PRIME_1_OFFSET(modSize) (modSize)
608
#define CAPI_PRIME_2_OFFSET(modSize) ((modSize)+(modSize)/2)
609
#define CAPI_EXPONENT_1_OFFSET(modSize) ((modSize)*2)
610
#define CAPI_EXPONENT_2_OFFSET(modSize) ((modSize)*2+(modSize)/2)
611
#define CAPI_COEFFICIENT_OFFSET(modSize) ((modSize)*3)
612
#define CAPI_PRIVATE_EXP_OFFSET(modSize) ((modSize)*3+(modSize)/2)
615
ckcapi_FetchPublicKey
617
ckcapiInternalObject *io
627
unsigned long modulus;
629
CAPI_RSA_KEY_BLOB *blob;
631
error = nss_ckcapi_FetchKeyContainer(io, &hProv, &keySpec, &hKey);
632
if (CKR_OK != error) {
635
kp = (ckcapiCert == io->type) ? &io->u.cert.key : &io->u.key.key;
637
rc = CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, buf, &bufLen);
641
buf = nss_ZNEWARRAY(NULL, char, bufLen);
642
rc = CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, buf, &bufLen);
646
/* validate the blob */
647
blob = (CAPI_RSA_KEY_BLOB *)buf;
648
if ((PUBLICKEYBLOB != blob->header.bType) ||
649
(0x02 != blob->header.bVersion) ||
650
(0x31415352 != blob->rsa.magic)) {
653
modulus = blob->rsa.bitlen/8;
657
kp->modulus.data = &blob->data[CAPI_MODULUS_OFFSET(modulus)];
658
kp->modulus.size = modulus;
659
ckcapi_ReverseData(&kp->modulus);
660
nss_ckcapi_IntToData(blob->rsa.pubexp, &kp->exponent,
661
kp->publicExponentData, &error);
666
CryptDestroyKey(hKey);
672
ckcapi_FetchPrivateKey
674
ckcapiInternalObject *io
684
unsigned long modulus;
686
CAPI_RSA_KEY_BLOB *blob;
688
error = nss_ckcapi_FetchKeyContainer(io, &hProv, &keySpec, &hKey);
689
if (CKR_OK != error) {
692
kp = (ckcapiCert == io->type) ? &io->u.cert.key : &io->u.key.key;
694
rc = CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, buf, &bufLen);
698
buf = nss_ZNEWARRAY(NULL, char, bufLen);
699
rc = CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, buf, &bufLen);
703
/* validate the blob */
704
blob = (CAPI_RSA_KEY_BLOB *)buf;
705
if ((PRIVATEKEYBLOB != blob->header.bType) ||
706
(0x02 != blob->header.bVersion) ||
707
(0x32415352 != blob->rsa.magic)) {
710
modulus = blob->rsa.bitlen/8;
711
kp->privateKey = buf;
714
kp->privateExponent.data = &blob->data[CAPI_PRIVATE_EXP_OFFSET(modulus)];
715
kp->privateExponent.size = modulus;
716
ckcapi_ReverseData(&kp->privateExponent);
717
kp->prime1.data = &blob->data[CAPI_PRIME_1_OFFSET(modulus)];
718
kp->prime1.size = modulus/2;
719
ckcapi_ReverseData(&kp->prime1);
720
kp->prime2.data = &blob->data[CAPI_PRIME_2_OFFSET(modulus)];
721
kp->prime2.size = modulus/2;
722
ckcapi_ReverseData(&kp->prime2);
723
kp->exponent1.data = &blob->data[CAPI_EXPONENT_1_OFFSET(modulus)];
724
kp->exponent1.size = modulus/2;
725
ckcapi_ReverseData(&kp->exponent1);
726
kp->exponent2.data = &blob->data[CAPI_EXPONENT_2_OFFSET(modulus)];
727
kp->exponent2.size = modulus/2;
728
ckcapi_ReverseData(&kp->exponent2);
729
kp->coefficient.data = &blob->data[CAPI_COEFFICIENT_OFFSET(modulus)];
730
kp->coefficient.size = modulus/2;
731
ckcapi_ReverseData(&kp->coefficient);
736
CryptDestroyKey(hKey);
743
ckcapi_PopulateModulusExponent
745
ckcapiInternalObject *io
748
if (ckcapiCert == io->type) {
749
ckcapi_CertPopulateModulusExponent(io);
751
ckcapi_FetchPublicKey(io);
757
* fetch the friendly name attribute.
758
* can only be called with ckcapiCert type objects!
763
ckcapiInternalObject *io
766
ckcapiCertObject *co = &io->u.cert;
768
PCCERT_CONTEXT certContext = io->u.cert.certContext;
769
char labelDataUTF16[128];
770
DWORD size = sizeof(labelDataUTF16);
771
DWORD size8 = sizeof(co->labelData);
774
rv = CertGetCertificateContextProperty(certContext,
775
CERT_FRIENDLY_NAME_PROP_ID, labelDataUTF16, &size);
777
co->labelData = nss_ckcapi_WideToUTF8((LPCWSTR)labelDataUTF16);
778
if ((CHAR *)NULL == co->labelData) {
781
size = strlen(co->labelData);
784
label = co->labelData;
785
/* we are presuming a user cert, make sure it has a nickname, even if
786
* Microsoft never gave it one */
787
if (!rv && co->hasID) {
788
DWORD mserror = GetLastError();
789
#define DEFAULT_NICKNAME "no Microsoft nickname"
790
label = DEFAULT_NICKNAME;
791
size = sizeof(DEFAULT_NICKNAME);
796
co->label.data = label;
797
co->label.size = size;
805
ckcapiInternalObject *io
808
ckcapiCertObject *co = &io->u.cert;
809
PCCERT_CONTEXT certContext = io->u.cert.certContext;
810
DWORD size = sizeof(co->derSerial);
812
BOOL rc = CryptEncodeObject(X509_ASN_ENCODING,
813
X509_MULTI_BYTE_INTEGER,
814
&certContext->pCertInfo->SerialNumber,
818
co->serial.data = co->derSerial;
819
co->serial.size = size;
830
ckcapiInternalObject *io
833
PCCERT_CONTEXT certContext = io->u.cert.certContext;
837
rc = CertGetCertificateContextProperty(certContext,
838
CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
842
io->idData = nss_ZNEWARRAY(NULL, char, size);
843
if (io->idData == NULL) {
847
rc = CertGetCertificateContextProperty(certContext,
848
CERT_KEY_IDENTIFIER_PROP_ID, io->idData, &size);
850
nss_ZFreeIf(io->idData);
854
io->id.data = io->idData;
860
* fetch the hash key.
863
ckcapi_CertFetchHashKey
865
ckcapiInternalObject *io
868
ckcapiCertObject *co = &io->u.cert;
869
PCCERT_CONTEXT certContext = io->u.cert.certContext;
870
DWORD size = certContext->cbCertEncoded;
871
DWORD max = sizeof(io->hashKeyData)-1;
874
/* make sure we don't over flow. NOTE: cutting the top of a cert is
875
* not a big issue because the signature for will be unique for the cert */
881
nsslibc_memcpy(io->hashKeyData,certContext->pbCertEncoded+offset, size);
882
io->hashKeyData[size] = (char)(io->objClass & 0xff);
884
io->hashKey.data = io->hashKeyData;
885
io->hashKey.size = size+1;
890
* fetch the hash key.
893
ckcapi_KeyFetchHashKey
895
ckcapiInternalObject *io
898
ckcapiKeyObject *ko = &io->u.key;
900
DWORD max = sizeof(io->hashKeyData)-2;
902
DWORD provLen = strlen(ko->provName);
903
DWORD containerLen = strlen(ko->containerName);
906
size = provLen + containerLen;
908
/* make sure we don't overflow, try to keep things unique */
910
DWORD diff = ((size - max)+1)/2;
912
containerLen -= diff;
913
size = provLen+containerLen;
916
nsslibc_memcpy(io->hashKeyData, ko->provName, provLen);
917
nsslibc_memcpy(&io->hashKeyData[provLen],
920
io->hashKeyData[size] = (char)(io->objClass & 0xff);
921
io->hashKeyData[size+1] = (char)(ko->provInfo.dwKeySpec & 0xff);
923
io->hashKey.data = io->hashKeyData;
924
io->hashKey.size = size+2;
929
* fetch the hash key.
934
ckcapiInternalObject *io
937
if (ckcapiCert == io->type) {
938
ckcapi_CertFetchHashKey(io);
940
ckcapi_KeyFetchHashKey(io);
946
ckcapi_FetchCertAttribute
948
ckcapiInternalObject *io,
949
CK_ATTRIBUTE_TYPE type
952
PCCERT_CONTEXT certContext = io->u.cert.certContext;
955
return &ckcapi_certClassItem;
957
return &ckcapi_trueItem;
960
return &ckcapi_falseItem;
961
case CKA_CERTIFICATE_TYPE:
962
return &ckcapi_x509Item;
964
if (0 == io->u.cert.label.size) {
965
ckcapi_FetchLabel(io);
967
return &io->u.cert.label;
969
if (0 == io->u.cert.subject.size) {
970
io->u.cert.subject.data = certContext->pCertInfo->Subject.pbData;
971
io->u.cert.subject.size = certContext->pCertInfo->Subject.cbData;
973
return &io->u.cert.subject;
975
if (0 == io->u.cert.issuer.size) {
976
io->u.cert.issuer.data = certContext->pCertInfo->Issuer.pbData;
977
io->u.cert.issuer.size = certContext->pCertInfo->Issuer.cbData;
979
return &io->u.cert.issuer;
980
case CKA_SERIAL_NUMBER:
981
if (0 == io->u.cert.serial.size) {
982
/* not exactly right. This should be the encoded serial number, but
983
* it's the decoded serial number! */
984
ckcapi_FetchSerial(io);
986
return &io->u.cert.serial;
988
if (0 == io->u.cert.derCert.size) {
989
io->u.cert.derCert.data = io->u.cert.certContext->pbCertEncoded;
990
io->u.cert.derCert.size = io->u.cert.certContext->cbCertEncoded;
992
return &io->u.cert.derCert;
994
if (!io->u.cert.hasID) {
997
if (0 == io->id.size) {
1008
ckcapi_FetchPubKeyAttribute
1010
ckcapiInternalObject *io,
1011
CK_ATTRIBUTE_TYPE type
1014
PRBool isCertType = (ckcapiCert == io->type);
1015
ckcapiKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key;
1019
return &ckcapi_pubKeyClassItem;
1024
case CKA_VERIFY_RECOVER:
1025
return &ckcapi_trueItem;
1027
case CKA_MODIFIABLE:
1030
return &ckcapi_falseItem;
1032
return &ckcapi_rsaItem;
1035
return &ckcapi_emptyItem;
1037
if (0 == io->u.cert.label.size) {
1038
ckcapi_FetchLabel(io);
1040
return &io->u.cert.label;
1043
return &ckcapi_emptyItem;
1045
if (0 == io->u.cert.subject.size) {
1046
PCCERT_CONTEXT certContext= io->u.cert.certContext;
1047
io->u.cert.subject.data = certContext->pCertInfo->Subject.pbData;
1048
io->u.cert.subject.size = certContext->pCertInfo->Subject.cbData;
1050
return &io->u.cert.subject;
1052
if (0 == kp->modulus.size) {
1053
ckcapi_PopulateModulusExponent(io);
1055
return &kp->modulus;
1056
case CKA_PUBLIC_EXPONENT:
1057
if (0 == kp->modulus.size) {
1058
ckcapi_PopulateModulusExponent(io);
1060
return &kp->exponent;
1062
if (0 == io->id.size) {
1073
ckcapi_FetchPrivKeyAttribute
1075
ckcapiInternalObject *io,
1076
CK_ATTRIBUTE_TYPE type
1079
PRBool isCertType = (ckcapiCert == io->type);
1080
ckcapiKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key;
1084
return &ckcapi_privKeyClassItem;
1089
case CKA_SIGN_RECOVER:
1090
return &ckcapi_trueItem;
1092
case CKA_PRIVATE: /* should move in the future */
1093
case CKA_MODIFIABLE:
1096
case CKA_EXTRACTABLE: /* will probably move in the future */
1097
case CKA_ALWAYS_SENSITIVE:
1098
case CKA_NEVER_EXTRACTABLE:
1099
return &ckcapi_falseItem;
1101
return &ckcapi_rsaItem;
1104
return &ckcapi_emptyItem;
1106
if (0 == io->u.cert.label.size) {
1107
ckcapi_FetchLabel(io);
1109
return &io->u.cert.label;
1112
return &ckcapi_emptyItem;
1114
if (0 == io->u.cert.subject.size) {
1115
PCCERT_CONTEXT certContext= io->u.cert.certContext;
1116
io->u.cert.subject.data = certContext->pCertInfo->Subject.pbData;
1117
io->u.cert.subject.size = certContext->pCertInfo->Subject.cbData;
1119
return &io->u.cert.subject;
1121
if (0 == kp->modulus.size) {
1122
ckcapi_PopulateModulusExponent(io);
1124
return &kp->modulus;
1125
case CKA_PUBLIC_EXPONENT:
1126
if (0 == kp->modulus.size) {
1127
ckcapi_PopulateModulusExponent(io);
1129
return &kp->exponent;
1130
case CKA_PRIVATE_EXPONENT:
1131
if (0 == kp->privateExponent.size) {
1132
ckcapi_FetchPrivateKey(io);
1134
return &kp->privateExponent;
1136
if (0 == kp->privateExponent.size) {
1137
ckcapi_FetchPrivateKey(io);
1141
if (0 == kp->privateExponent.size) {
1142
ckcapi_FetchPrivateKey(io);
1145
case CKA_EXPONENT_1:
1146
if (0 == kp->privateExponent.size) {
1147
ckcapi_FetchPrivateKey(io);
1149
return &kp->exponent1;
1150
case CKA_EXPONENT_2:
1151
if (0 == kp->privateExponent.size) {
1152
ckcapi_FetchPrivateKey(io);
1154
return &kp->exponent2;
1155
case CKA_COEFFICIENT:
1156
if (0 == kp->privateExponent.size) {
1157
ckcapi_FetchPrivateKey(io);
1159
return &kp->coefficient;
1161
if (0 == io->id.size) {
1171
nss_ckcapi_FetchAttribute
1173
ckcapiInternalObject *io,
1174
CK_ATTRIBUTE_TYPE type
1179
if (io->type == ckcapiRaw) {
1180
for( i = 0; i < io->u.raw.n; i++ ) {
1181
if( type == io->u.raw.types[i] ) {
1182
return &io->u.raw.items[i];
1187
/* deal with the common attributes */
1188
switch (io->objClass) {
1189
case CKO_CERTIFICATE:
1190
return ckcapi_FetchCertAttribute(io, type);
1191
case CKO_PRIVATE_KEY:
1192
return ckcapi_FetchPrivKeyAttribute(io, type);
1193
case CKO_PUBLIC_KEY:
1194
return ckcapi_FetchPubKeyAttribute(io, type);
1200
* check to see if the certificate already exists
1205
ckcapiInternalObject **io
1210
ckcapiInternalObject **listp = NULL;
1211
CK_ATTRIBUTE myTemplate[2];
1212
CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE;
1213
CK_ULONG templateCount = 2;
1215
PRBool found = PR_FALSE;
1217
myTemplate[0].type = CKA_CLASS;
1218
myTemplate[0].pValue = &cert_class;
1219
myTemplate[0].ulValueLen = sizeof(cert_class);
1220
myTemplate[1].type = CKA_VALUE;
1221
myTemplate[1].pValue = value->data;
1222
myTemplate[1].ulValueLen = value->size;
1224
count = nss_ckcapi_collect_all_certs(myTemplate, templateCount, &listp,
1233
for (i=1; i < count; i++) {
1234
nss_ckcapi_DestroyInternalObject(listp[i]);
1241
ckcapi_cert_hasEmail
1243
PCCERT_CONTEXT certContext
1248
count = CertGetNameString(certContext, CERT_NAME_EMAIL_TYPE,
1251
return count > 1 ? PR_TRUE : PR_FALSE;
1257
PCCERT_CONTEXT certContext
1260
return CertCompareCertificateName(certContext->dwCertEncodingType,
1261
&certContext->pCertInfo->Issuer, &certContext->pCertInfo->Subject);
1267
PCCERT_CONTEXT certContext
1270
PCERT_EXTENSION extension;
1271
CERT_BASIC_CONSTRAINTS2_INFO basicInfo;
1272
DWORD size = sizeof(basicInfo);
1275
extension = CertFindExtension (szOID_BASIC_CONSTRAINTS,
1276
certContext->pCertInfo->cExtension,
1277
certContext->pCertInfo->rgExtension);
1278
if ((PCERT_EXTENSION) NULL == extension ) {
1281
rc = CryptDecodeObject(X509_ASN_ENCODING, szOID_BASIC_CONSTRAINTS2,
1282
extension->Value.pbData, extension->Value.cbData,
1283
0, &basicInfo, &size);
1287
return (PRBool) basicInfo.fCA;
1290
static CRYPT_KEY_PROV_INFO *
1291
ckcapi_cert_getPrivateKeyInfo
1293
PCCERT_CONTEXT certContext,
1298
CRYPT_HASH_BLOB msKeyID;
1300
CRYPT_KEY_PROV_INFO *prov = NULL;
1302
msKeyID.cbData = keyID->size;
1303
msKeyID.pbData = keyID->data;
1305
rc = CryptGetKeyIdentifierProperty(
1307
CERT_KEY_PROV_INFO_PROP_ID,
1308
0, NULL, NULL, NULL, &size);
1310
return (CRYPT_KEY_PROV_INFO *)NULL;
1312
prov = (CRYPT_KEY_PROV_INFO *)nss_ZAlloc(NULL, size);
1313
if ((CRYPT_KEY_PROV_INFO *)prov == NULL) {
1314
return (CRYPT_KEY_PROV_INFO *) NULL;
1316
rc = CryptGetKeyIdentifierProperty(
1318
CERT_KEY_PROV_INFO_PROP_ID,
1319
0, NULL, NULL, prov, &size);
1322
return (CRYPT_KEY_PROV_INFO *)NULL;
1328
static CRYPT_KEY_PROV_INFO *
1329
ckcapi_cert_getProvInfo
1331
ckcapiInternalObject *io
1336
CRYPT_KEY_PROV_INFO *prov = NULL;
1338
rc = CertGetCertificateContextProperty(
1339
io->u.cert.certContext,
1340
CERT_KEY_PROV_INFO_PROP_ID,
1343
return (CRYPT_KEY_PROV_INFO *)NULL;
1345
prov = (CRYPT_KEY_PROV_INFO *)nss_ZAlloc(NULL, size);
1346
if ((CRYPT_KEY_PROV_INFO *)prov == NULL) {
1347
return (CRYPT_KEY_PROV_INFO *) NULL;
1349
rc = CertGetCertificateContextProperty(
1350
io->u.cert.certContext,
1351
CERT_KEY_PROV_INFO_PROP_ID,
1355
return (CRYPT_KEY_PROV_INFO *)NULL;
1361
/* forward declaration */
1363
ckcapi_removeObjectFromHash
1365
ckcapiInternalObject *io
1369
* Finalize - unneeded
1371
* IsTokenObject - CK_TRUE
1381
ckcapi_mdObject_Destroy
1383
NSSCKMDObject *mdObject,
1384
NSSCKFWObject *fwObject,
1385
NSSCKMDSession *mdSession,
1386
NSSCKFWSession *fwSession,
1387
NSSCKMDToken *mdToken,
1388
NSSCKFWToken *fwToken,
1389
NSSCKMDInstance *mdInstance,
1390
NSSCKFWInstance *fwInstance
1393
ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
1394
CK_OBJECT_CLASS objClass;
1398
PRBool isCertType = (PRBool)(ckcapiCert == io->type);
1399
HCERTSTORE hStore = 0;
1401
if (ckcapiRaw == io->type) {
1402
/* there is not 'object write protected' error, use the next best thing */
1403
return CKR_TOKEN_WRITE_PROTECTED;
1406
objClass = io->objClass;
1407
if (CKO_CERTIFICATE == objClass) {
1408
PCCERT_CONTEXT certContext;
1411
hStore = CertOpenSystemStore(0, io->u.cert.certStore);
1416
certContext = CertFindCertificateInStore(hStore, X509_ASN_ENCODING, 0,
1417
CERT_FIND_EXISTING, io->u.cert.certContext, NULL);
1418
if ((PCCERT_CONTEXT)NULL == certContext) {
1422
rc = CertDeleteCertificateFromStore(certContext);
1423
CertFreeCertificateContext(certContext);
1425
char *provName = NULL;
1426
char *containerName = NULL;
1428
CRYPT_HASH_BLOB msKeyID;
1430
if (0 == io->id.size) {
1435
CRYPT_KEY_PROV_INFO * provInfo = ckcapi_cert_getProvInfo(io);
1436
provName = nss_ckcapi_WideToUTF8(provInfo->pwszProvName);
1437
containerName = nss_ckcapi_WideToUTF8(provInfo->pwszContainerName);
1438
provType = provInfo->dwProvType;
1439
nss_ZFreeIf(provInfo);
1441
provName = io->u.key.provName;
1442
containerName = io->u.key.containerName;
1443
provType = io->u.key.provInfo.dwProvType;
1444
io->u.key.provName = NULL;
1445
io->u.key.containerName = NULL;
1447
/* first remove the key id pointer */
1448
msKeyID.cbData = io->id.size;
1449
msKeyID.pbData = io->id.data;
1450
rc = CryptSetKeyIdentifierProperty(&msKeyID,
1451
CERT_KEY_PROV_INFO_PROP_ID, CRYPT_KEYID_DELETE_FLAG, NULL, NULL, NULL);
1453
rc = CryptAcquireContext(&hProv, containerName, provName, provType,
1454
CRYPT_DELETEKEYSET);
1456
nss_ZFreeIf(provName);
1457
nss_ZFreeIf(containerName);
1462
CertCloseStore(hStore, 0);
1465
msError = GetLastError();
1466
return CKR_GENERAL_ERROR;
1469
/* remove it from the hash */
1470
ckcapi_removeObjectFromHash(io);
1472
/* free the puppy.. */
1473
nss_ckcapi_DestroyInternalObject(io);
1478
ckcapi_mdObject_IsTokenObject
1480
NSSCKMDObject *mdObject,
1481
NSSCKFWObject *fwObject,
1482
NSSCKMDSession *mdSession,
1483
NSSCKFWSession *fwSession,
1484
NSSCKMDToken *mdToken,
1485
NSSCKFWToken *fwToken,
1486
NSSCKMDInstance *mdInstance,
1487
NSSCKFWInstance *fwInstance
1494
ckcapi_mdObject_GetAttributeCount
1496
NSSCKMDObject *mdObject,
1497
NSSCKFWObject *fwObject,
1498
NSSCKMDSession *mdSession,
1499
NSSCKFWSession *fwSession,
1500
NSSCKMDToken *mdToken,
1501
NSSCKFWToken *fwToken,
1502
NSSCKMDInstance *mdInstance,
1503
NSSCKFWInstance *fwInstance,
1507
ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
1509
if (ckcapiRaw == io->type) {
1512
switch (io->objClass) {
1513
case CKO_CERTIFICATE:
1514
return certAttrsCount;
1515
case CKO_PUBLIC_KEY:
1516
return pubKeyAttrsCount;
1517
case CKO_PRIVATE_KEY:
1518
return privKeyAttrsCount;
1526
ckcapi_mdObject_GetAttributeTypes
1528
NSSCKMDObject *mdObject,
1529
NSSCKFWObject *fwObject,
1530
NSSCKMDSession *mdSession,
1531
NSSCKFWSession *fwSession,
1532
NSSCKMDToken *mdToken,
1533
NSSCKFWToken *fwToken,
1534
NSSCKMDInstance *mdInstance,
1535
NSSCKFWInstance *fwInstance,
1536
CK_ATTRIBUTE_TYPE_PTR typeArray,
1540
ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
1542
CK_RV error = CKR_OK;
1543
const CK_ATTRIBUTE_TYPE *attrs = NULL;
1544
CK_ULONG size = ckcapi_mdObject_GetAttributeCount(
1545
mdObject, fwObject, mdSession, fwSession,
1546
mdToken, fwToken, mdInstance, fwInstance, &error);
1548
if( size != ulCount ) {
1549
return CKR_BUFFER_TOO_SMALL;
1551
if (io->type == ckcapiRaw) {
1552
attrs = io->u.raw.types;
1553
} else switch(io->objClass) {
1554
case CKO_CERTIFICATE:
1557
case CKO_PUBLIC_KEY:
1558
attrs = pubKeyAttrs;
1560
case CKO_PRIVATE_KEY:
1561
attrs = privKeyAttrs;
1567
for( i = 0; i < size; i++) {
1568
typeArray[i] = attrs[i];
1575
ckcapi_mdObject_GetAttributeSize
1577
NSSCKMDObject *mdObject,
1578
NSSCKFWObject *fwObject,
1579
NSSCKMDSession *mdSession,
1580
NSSCKFWSession *fwSession,
1581
NSSCKMDToken *mdToken,
1582
NSSCKFWToken *fwToken,
1583
NSSCKMDInstance *mdInstance,
1584
NSSCKFWInstance *fwInstance,
1585
CK_ATTRIBUTE_TYPE attribute,
1589
ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
1593
b = nss_ckcapi_FetchAttribute(io, attribute);
1595
if ((const NSSItem *)NULL == b) {
1596
*pError = CKR_ATTRIBUTE_TYPE_INVALID;
1603
ckcapi_mdObject_SetAttribute
1605
NSSCKMDObject *mdObject,
1606
NSSCKFWObject *fwObject,
1607
NSSCKMDSession *mdSession,
1608
NSSCKFWSession *fwSession,
1609
NSSCKMDToken *mdToken,
1610
NSSCKFWToken *fwToken,
1611
NSSCKMDInstance *mdInstance,
1612
NSSCKFWInstance *fwInstance,
1613
CK_ATTRIBUTE_TYPE attribute,
1621
ckcapi_mdObject_GetAttribute
1623
NSSCKMDObject *mdObject,
1624
NSSCKFWObject *fwObject,
1625
NSSCKMDSession *mdSession,
1626
NSSCKFWSession *fwSession,
1627
NSSCKMDToken *mdToken,
1628
NSSCKFWToken *fwToken,
1629
NSSCKMDInstance *mdInstance,
1630
NSSCKFWInstance *fwInstance,
1631
CK_ATTRIBUTE_TYPE attribute,
1636
ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
1638
mdItem.needsFreeing = PR_FALSE;
1639
mdItem.item = (NSSItem*)nss_ckcapi_FetchAttribute(io, attribute);
1641
if ((NSSItem *)NULL == mdItem.item) {
1642
*pError = CKR_ATTRIBUTE_TYPE_INVALID;
1649
ckcapi_mdObject_GetObjectSize
1651
NSSCKMDObject *mdObject,
1652
NSSCKFWObject *fwObject,
1653
NSSCKMDSession *mdSession,
1654
NSSCKFWSession *fwSession,
1655
NSSCKMDToken *mdToken,
1656
NSSCKFWToken *fwToken,
1657
NSSCKMDInstance *mdInstance,
1658
NSSCKFWInstance *fwInstance,
1662
ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
1665
/* size is irrelevant to this token */
1669
static const NSSCKMDObject
1670
ckcapi_prototype_mdObject = {
1671
(void *)NULL, /* etc */
1672
NULL, /* Finalize */
1673
ckcapi_mdObject_Destroy,
1674
ckcapi_mdObject_IsTokenObject,
1675
ckcapi_mdObject_GetAttributeCount,
1676
ckcapi_mdObject_GetAttributeTypes,
1677
ckcapi_mdObject_GetAttributeSize,
1678
ckcapi_mdObject_GetAttribute,
1679
NULL, /* FreeAttribute */
1680
ckcapi_mdObject_SetAttribute,
1681
ckcapi_mdObject_GetObjectSize,
1682
(void *)NULL /* null terminator */
1685
static nssHash *ckcapiInternalObjectHash = NULL;
1687
NSS_IMPLEMENT NSSCKMDObject *
1688
nss_ckcapi_CreateMDObject
1691
ckcapiInternalObject *io,
1695
if ((nssHash *)NULL == ckcapiInternalObjectHash) {
1696
ckcapiInternalObjectHash = nssHash_CreateItem(NULL, 10);
1698
if (ckcapiCert == io->type) {
1699
/* the hash key, not a cryptographic key */
1700
NSSItem *key = &io->hashKey;
1701
ckcapiInternalObject *old_o = NULL;
1703
if (key->size == 0) {
1704
ckcapi_FetchHashKey(io);
1706
old_o = (ckcapiInternalObject *)
1707
nssHash_Lookup(ckcapiInternalObjectHash, key);
1709
nssHash_Add(ckcapiInternalObjectHash, key, io);
1710
} else if (old_o != io) {
1711
nss_ckcapi_DestroyInternalObject(io);
1716
if ( (void*)NULL == io->mdObject.etc) {
1717
(void) nsslibc_memcpy(&io->mdObject,&ckcapi_prototype_mdObject,
1718
sizeof(ckcapi_prototype_mdObject));
1719
io->mdObject.etc = (void *)io;
1721
return &io->mdObject;
1725
ckcapi_removeObjectFromHash
1727
ckcapiInternalObject *io
1730
NSSItem *key = &io->hashKey;
1732
if ((nssHash *)NULL == ckcapiInternalObjectHash) {
1735
if (key->size == 0) {
1736
ckcapi_FetchHashKey(io);
1738
nssHash_Remove(ckcapiInternalObjectHash, key);
1743
nss_ckcapi_DestroyInternalObject
1745
ckcapiInternalObject *io
1752
CertFreeCertificateContext(io->u.cert.certContext);
1753
nss_ZFreeIf(io->u.cert.labelData);
1754
nss_ZFreeIf(io->u.cert.key.privateKey);
1755
nss_ZFreeIf(io->u.cert.key.pubKey);
1756
nss_ZFreeIf(io->idData);
1759
nss_ZFreeIf(io->u.key.provInfo.pwszContainerName);
1760
nss_ZFreeIf(io->u.key.provInfo.pwszProvName);
1761
nss_ZFreeIf(io->u.key.provName);
1762
nss_ZFreeIf(io->u.key.containerName);
1763
nss_ZFreeIf(io->u.key.key.privateKey);
1764
nss_ZFreeIf(io->u.key.key.pubKey);
1765
if (0 != io->u.key.hProv) {
1766
CryptReleaseContext(io->u.key.hProv, 0);
1768
nss_ZFreeIf(io->idData);
1775
static ckcapiInternalObject *
1776
nss_ckcapi_CreateCertificate
1778
NSSCKFWSession *fwSession,
1779
CK_ATTRIBUTE_PTR pTemplate,
1780
CK_ULONG ulAttributeCount,
1787
ckcapiInternalObject *io = NULL;
1788
PCCERT_CONTEXT certContext = NULL;
1789
PCCERT_CONTEXT storedCertContext = NULL;
1790
CRYPT_KEY_PROV_INFO *prov_info = NULL;
1791
char *nickname = NULL;
1792
HCERTSTORE hStore = 0;
1798
*pError = nss_ckcapi_GetAttribute(CKA_VALUE, pTemplate,
1799
ulAttributeCount, &value);
1801
if (CKR_OK != *pError) {
1802
return (ckcapiInternalObject *)NULL;
1805
*pError = nss_ckcapi_GetAttribute(CKA_ID, pTemplate,
1806
ulAttributeCount, &keyID);
1808
if (CKR_OK != *pError) {
1809
return (ckcapiInternalObject *)NULL;
1812
if (ckcapi_cert_exists(&value, &io)) {
1816
/* OK, we are creating a new one, figure out what store it belongs to..
1817
* first get a certContext handle.. */
1818
certContext = CertCreateCertificateContext(X509_ASN_ENCODING,
1819
value.data, value.size);
1820
if ((PCCERT_CONTEXT) NULL == certContext) {
1821
msError = GetLastError();
1822
*pError = CKR_ATTRIBUTE_VALUE_INVALID;
1826
/* do we have a private key laying around... */
1827
prov_info = ckcapi_cert_getPrivateKeyInfo(certContext, &keyID);
1829
CRYPT_DATA_BLOB msKeyID;
1832
rc = CertSetCertificateContextProperty(certContext,
1833
CERT_KEY_PROV_INFO_PROP_ID,
1835
nss_ZFreeIf(prov_info);
1837
msError = GetLastError();
1838
*pError = CKR_DEVICE_ERROR;
1841
msKeyID.cbData = keyID.size;
1842
msKeyID.pbData = keyID.data;
1843
rc = CertSetCertificateContextProperty(certContext,
1844
CERT_KEY_IDENTIFIER_PROP_ID,
1847
msError = GetLastError();
1848
*pError = CKR_DEVICE_ERROR;
1852
/* does it look like a CA */
1853
} else if (ckcapi_cert_isCA(certContext)) {
1854
storeStr = ckcapi_cert_isRoot(certContext) ? "CA" : "Root";
1855
/* does it look like an S/MIME cert */
1856
} else if (ckcapi_cert_hasEmail(certContext)) {
1857
storeStr = "AddressBook";
1859
/* just pick a store */
1863
/* get the nickname, not an error if we can't find it */
1864
nickname = nss_ckcapi_GetStringAttribute(CKA_LABEL, pTemplate,
1865
ulAttributeCount, &dummy);
1867
LPWSTR nicknameUTF16 = NULL;
1868
CRYPT_DATA_BLOB nicknameBlob;
1870
nicknameUTF16 = nss_ckcapi_UTF8ToWide(nickname);
1871
nss_ZFreeIf(nickname);
1873
if ((LPWSTR)NULL == nicknameUTF16) {
1874
*pError = CKR_HOST_MEMORY;
1877
nicknameBlob.cbData = nss_ckcapi_WideSize(nicknameUTF16);
1878
nicknameBlob.pbData = (BYTE *)nicknameUTF16;
1879
rc = CertSetCertificateContextProperty(certContext,
1880
CERT_FRIENDLY_NAME_PROP_ID, 0, &nicknameBlob);
1881
nss_ZFreeIf(nicknameUTF16);
1883
msError = GetLastError();
1884
*pError = CKR_DEVICE_ERROR;
1889
hStore = CertOpenSystemStore((HCRYPTPROV) NULL, storeStr);
1891
msError = GetLastError();
1892
*pError = CKR_DEVICE_ERROR;
1896
rc = CertAddCertificateContextToStore(hStore, certContext,
1897
CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES, &storedCertContext);
1898
CertFreeCertificateContext(certContext);
1900
CertCloseStore(hStore, 0);
1903
msError = GetLastError();
1904
*pError = CKR_DEVICE_ERROR;
1908
io = nss_ZNEW(NULL, ckcapiInternalObject);
1909
if ((ckcapiInternalObject *)NULL == io) {
1910
*pError = CKR_HOST_MEMORY;
1913
io->type = ckcapiCert;
1914
io->objClass = CKO_CERTIFICATE;
1915
io->u.cert.certContext = storedCertContext;
1916
io->u.cert.hasID = hasID;
1921
CertFreeCertificateContext(certContext);
1924
if (storedCertContext) {
1925
CertFreeCertificateContext(storedCertContext);
1926
storedCertContext = NULL;
1929
CertCloseStore(hStore, 0);
1931
return (ckcapiInternalObject *)NULL;
1936
ckcapi_getDefaultProvider
1943
DWORD nameLength = 0;
1945
rc = CryptGetDefaultProvider(PROV_RSA_FULL, NULL, CRYPT_USER_DEFAULT, NULL,
1948
return (char *)NULL;
1951
name = nss_ZNEWARRAY(NULL, char, nameLength);
1952
if ((char *)NULL == name ) {
1953
return (char *)NULL;
1955
rc = CryptGetDefaultProvider(PROV_RSA_FULL, NULL, CRYPT_USER_DEFAULT, name,
1959
return (char *)NULL;
1977
rstat = UuidCreate(&uuid);
1978
rstat = UuidToString(&uuid, &uuidStr);
1980
/* convert it from rcp memory to our own */
1981
container = nssUTF8_Duplicate(uuidStr, NULL);
1982
RpcStringFree(&uuidStr);
1988
ckcapi_buildPrivateKeyBlob
1992
NSSItem *publicExponent,
1993
NSSItem *privateExponent,
1998
NSSItem *coefficient,
1999
PRBool isKeyExchange
2002
CAPI_RSA_KEY_BLOB *keyBlobData = NULL;
2003
unsigned char *target;
2004
unsigned long modSize = modulus->size;
2005
unsigned long dataSize;
2006
CK_RV error = CKR_OK;
2008
/* validate extras */
2009
if (privateExponent->size != modSize) {
2010
error = CKR_ATTRIBUTE_VALUE_INVALID;
2013
if (prime1->size != modSize/2) {
2014
error = CKR_ATTRIBUTE_VALUE_INVALID;
2017
if (prime2->size != modSize/2) {
2018
error = CKR_ATTRIBUTE_VALUE_INVALID;
2021
if (exponent1->size != modSize/2) {
2022
error = CKR_ATTRIBUTE_VALUE_INVALID;
2025
if (exponent2->size != modSize/2) {
2026
error = CKR_ATTRIBUTE_VALUE_INVALID;
2029
if (coefficient->size != modSize/2) {
2030
error = CKR_ATTRIBUTE_VALUE_INVALID;
2033
dataSize = (modSize*4)+(modSize/2) + sizeof(CAPI_RSA_KEY_BLOB);
2034
keyBlobData = (CAPI_RSA_KEY_BLOB *)nss_ZAlloc(NULL, dataSize);
2035
if ((CAPI_RSA_KEY_BLOB *)NULL == keyBlobData) {
2036
error = CKR_HOST_MEMORY;
2040
keyBlobData->header.bType = PRIVATEKEYBLOB;
2041
keyBlobData->header.bVersion = 0x02;
2042
keyBlobData->header.reserved = 0x00;
2043
keyBlobData->header.aiKeyAlg = isKeyExchange ? CALG_RSA_KEYX:CALG_RSA_SIGN;
2044
keyBlobData->rsa.magic = 0x32415352;
2045
keyBlobData->rsa.bitlen = modSize * 8;
2046
keyBlobData->rsa.pubexp = nss_ckcapi_DataToInt(publicExponent,&error);
2047
if (CKR_OK != error) {
2051
target = &keyBlobData->data[CAPI_MODULUS_OFFSET(modSize)];
2052
nsslibc_memcpy(target, modulus->data, modulus->size);
2053
modulus->data = target;
2054
ckcapi_ReverseData(modulus);
2056
target = &keyBlobData->data[CAPI_PRIVATE_EXP_OFFSET(modSize)];
2057
nsslibc_memcpy(target, privateExponent->data, privateExponent->size);
2058
privateExponent->data = target;
2059
ckcapi_ReverseData(privateExponent);
2061
target = &keyBlobData->data[CAPI_PRIME_1_OFFSET(modSize)];
2062
nsslibc_memcpy(target, prime1->data, prime1->size);
2063
prime1->data = target;
2064
ckcapi_ReverseData(prime1);
2066
target = &keyBlobData->data[CAPI_PRIME_2_OFFSET(modSize)];
2067
nsslibc_memcpy(target, prime2->data, prime2->size);
2068
prime2->data = target;
2069
ckcapi_ReverseData(prime2);
2071
target = &keyBlobData->data[CAPI_EXPONENT_1_OFFSET(modSize)];
2072
nsslibc_memcpy(target, exponent1->data, exponent1->size);
2073
exponent1->data = target;
2074
ckcapi_ReverseData(exponent1);
2076
target = &keyBlobData->data[CAPI_EXPONENT_2_OFFSET(modSize)];
2077
nsslibc_memcpy(target, exponent2->data, exponent2->size);
2078
exponent2->data = target;
2079
ckcapi_ReverseData(exponent2);
2081
target = &keyBlobData->data[CAPI_COEFFICIENT_OFFSET(modSize)];
2082
nsslibc_memcpy(target, coefficient->data, coefficient->size);
2083
coefficient->data = target;
2084
ckcapi_ReverseData(coefficient);
2086
keyBlob->data = keyBlobData;
2087
keyBlob->size = dataSize;
2092
nss_ZFreeIf(keyBlobData);
2096
static ckcapiInternalObject *
2097
nss_ckcapi_CreatePrivateKey
2099
NSSCKFWSession *fwSession,
2100
CK_ATTRIBUTE_PTR pTemplate,
2101
CK_ULONG ulAttributeCount,
2106
NSSItem publicExponent;
2107
NSSItem privateExponent;
2112
NSSItem coefficient;
2115
ckcapiInternalObject *io = NULL;
2116
char *providerName = NULL;
2117
char *containerName = NULL;
2118
char *idData = NULL;
2119
CRYPT_KEY_PROV_INFO provInfo;
2120
CRYPT_HASH_BLOB msKeyID;
2121
CK_KEY_TYPE keyType;
2122
HCRYPTPROV hProv = 0;
2129
keyType = nss_ckcapi_GetULongAttribute
2130
(CKA_KEY_TYPE, pTemplate, ulAttributeCount, pError);
2131
if (CKR_OK != *pError) {
2132
return (ckcapiInternalObject *)NULL;
2134
if (CKK_RSA != keyType) {
2135
*pError = CKR_ATTRIBUTE_VALUE_INVALID;
2136
return (ckcapiInternalObject *)NULL;
2139
decrypt = nss_ckcapi_GetBoolAttribute(CKA_DECRYPT,
2140
pTemplate, ulAttributeCount, pError);
2141
if (CKR_TEMPLATE_INCOMPLETE == *pError) {
2142
decrypt = PR_TRUE; /* default to true */
2144
decrypt = decrypt || nss_ckcapi_GetBoolAttribute(CKA_UNWRAP,
2145
pTemplate, ulAttributeCount, pError);
2146
if (CKR_TEMPLATE_INCOMPLETE == *pError) {
2147
decrypt = PR_TRUE; /* default to true */
2149
keySpec = decrypt ? AT_KEYEXCHANGE : AT_SIGNATURE;
2151
*pError = nss_ckcapi_GetAttribute(CKA_MODULUS, pTemplate,
2152
ulAttributeCount, &modulus);
2153
if (CKR_OK != *pError) {
2154
return (ckcapiInternalObject *)NULL;
2156
*pError = nss_ckcapi_GetAttribute(CKA_PUBLIC_EXPONENT, pTemplate,
2157
ulAttributeCount, &publicExponent);
2158
if (CKR_OK != *pError) {
2159
return (ckcapiInternalObject *)NULL;
2161
*pError = nss_ckcapi_GetAttribute(CKA_PRIVATE_EXPONENT, pTemplate,
2162
ulAttributeCount, &privateExponent);
2163
if (CKR_OK != *pError) {
2164
return (ckcapiInternalObject *)NULL;
2166
*pError = nss_ckcapi_GetAttribute(CKA_PRIME_1, pTemplate,
2167
ulAttributeCount, &prime1);
2168
if (CKR_OK != *pError) {
2169
return (ckcapiInternalObject *)NULL;
2171
*pError = nss_ckcapi_GetAttribute(CKA_PRIME_2, pTemplate,
2172
ulAttributeCount, &prime2);
2173
if (CKR_OK != *pError) {
2174
return (ckcapiInternalObject *)NULL;
2176
*pError = nss_ckcapi_GetAttribute(CKA_EXPONENT_1, pTemplate,
2177
ulAttributeCount, &exponent1);
2178
if (CKR_OK != *pError) {
2179
return (ckcapiInternalObject *)NULL;
2181
*pError = nss_ckcapi_GetAttribute(CKA_EXPONENT_2, pTemplate,
2182
ulAttributeCount, &exponent2);
2183
if (CKR_OK != *pError) {
2184
return (ckcapiInternalObject *)NULL;
2186
*pError = nss_ckcapi_GetAttribute(CKA_COEFFICIENT, pTemplate,
2187
ulAttributeCount, &coefficient);
2188
if (CKR_OK != *pError) {
2189
return (ckcapiInternalObject *)NULL;
2191
*pError = nss_ckcapi_GetAttribute(CKA_ID, pTemplate,
2192
ulAttributeCount, &keyID);
2193
if (CKR_OK != *pError) {
2194
return (ckcapiInternalObject *)NULL;
2196
providerName = ckcapi_getDefaultProvider(pError);
2197
if ((char *)NULL == providerName ) {
2198
return (ckcapiInternalObject *)NULL;
2200
containerName = ckcapi_getContainer(pError, &keyID);
2201
if ((char *)NULL == providerName ) {
2204
rc = CryptAcquireContext(&hProv, containerName, providerName,
2205
PROV_RSA_FULL, CRYPT_NEWKEYSET);
2207
msError = GetLastError();
2208
*pError = CKR_DEVICE_ERROR;
2212
*pError = ckcapi_buildPrivateKeyBlob(
2223
if (CKR_OK != *pError) {
2227
rc = CryptImportKey(hProv, keyBlob.data, keyBlob.size,
2228
0, CRYPT_EXPORTABLE, &hKey);
2230
msError = GetLastError();
2231
*pError = CKR_DEVICE_ERROR;
2235
idData = nss_ZNEWARRAY(NULL, char, keyID.size);
2236
if ((void *)NULL == idData) {
2237
*pError = CKR_HOST_MEMORY;
2240
nsslibc_memcpy(idData, keyID.data, keyID.size);
2242
provInfo.pwszContainerName = nss_ckcapi_UTF8ToWide(containerName);
2243
provInfo.pwszProvName = nss_ckcapi_UTF8ToWide(providerName);
2244
provInfo.dwProvType = PROV_RSA_FULL;
2245
provInfo.dwFlags = 0;
2246
provInfo.cProvParam = 0;
2247
provInfo.rgProvParam = NULL;
2248
provInfo.dwKeySpec = keySpec;
2250
msKeyID.cbData = keyID.size;
2251
msKeyID.pbData = keyID.data;
2253
rc = CryptSetKeyIdentifierProperty(&msKeyID, CERT_KEY_PROV_INFO_PROP_ID,
2254
0, NULL, NULL, &provInfo);
2259
/* handle error here */
2260
io = nss_ZNEW(NULL, ckcapiInternalObject);
2261
if ((ckcapiInternalObject *)NULL == io) {
2262
*pError = CKR_HOST_MEMORY;
2265
io->type = ckcapiBareKey;
2266
io->objClass = CKO_PRIVATE_KEY;
2267
io->u.key.provInfo = provInfo;
2268
io->u.key.provName = providerName;
2269
io->u.key.containerName = containerName;
2270
io->u.key.hProv = hProv; /* save the handle */
2271
io->idData = idData;
2272
io->id.data = idData;
2273
io->id.size = keyID.size;
2274
/* done with the key handle */
2275
CryptDestroyKey(hKey);
2279
nss_ZFreeIf(containerName);
2280
nss_ZFreeIf(providerName);
2281
nss_ZFreeIf(idData);
2283
CryptReleaseContext(hProv, 0);
2286
CryptDestroyKey(hKey);
2288
return (ckcapiInternalObject *)NULL;
2292
NSS_EXTERN NSSCKMDObject *
2293
nss_ckcapi_CreateObject
2295
NSSCKFWSession *fwSession,
2296
CK_ATTRIBUTE_PTR pTemplate,
2297
CK_ULONG ulAttributeCount,
2301
CK_OBJECT_CLASS objClass;
2302
ckcapiInternalObject *io;
2306
* only create token objects
2308
isToken = nss_ckcapi_GetBoolAttribute(CKA_TOKEN, pTemplate,
2309
ulAttributeCount, pError);
2310
if (CKR_OK != *pError) {
2311
return (NSSCKMDObject *) NULL;
2314
*pError = CKR_ATTRIBUTE_VALUE_INVALID;
2315
return (NSSCKMDObject *) NULL;
2319
* only create keys and certs.
2321
objClass = nss_ckcapi_GetULongAttribute(CKA_CLASS, pTemplate,
2322
ulAttributeCount, pError);
2323
if (CKR_OK != *pError) {
2324
return (NSSCKMDObject *) NULL;
2327
if (objClass == CKO_PUBLIC_KEY) {
2328
return CKR_OK; /* fake public key creation, happens as a side effect of
2329
* private key creation */
2332
if (objClass == CKO_CERTIFICATE) {
2333
io = nss_ckcapi_CreateCertificate(fwSession, pTemplate,
2334
ulAttributeCount, pError);
2335
} else if (objClass == CKO_PRIVATE_KEY) {
2336
io = nss_ckcapi_CreatePrivateKey(fwSession, pTemplate,
2337
ulAttributeCount, pError);
2339
*pError = CKR_ATTRIBUTE_VALUE_INVALID;
2342
if ((ckcapiInternalObject *)NULL == io) {
2343
return (NSSCKMDObject *) NULL;
2345
return nss_ckcapi_CreateMDObject(NULL, io, pError);