~ubuntu-branches/ubuntu/trusty/xulrunner/trusty

« back to all changes in this revision

Viewing changes to security/nss-fips/lib/ckfw/capi/cobject.c

  • Committer: Bazaar Package Importer
  • Author(s): Devid Antonio Filoni
  • Date: 2008-08-25 13:04:18 UTC
  • mfrom: (1.1.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20080825130418-ck1i2ms384tzb9m0
Tags: 1.8.1.16+nobinonly-0ubuntu1
* New upstream release (taken from upstream CVS), LP: #254618.
* Fix MFSA 2008-35, MFSA 2008-34, MFSA 2008-33, MFSA 2008-32, MFSA 2008-31,
  MFSA 2008-30, MFSA 2008-29, MFSA 2008-28, MFSA 2008-27, MFSA 2008-25,
  MFSA 2008-24, MFSA 2008-23, MFSA 2008-22, MFSA 2008-21, MFSA 2008-26 also
  known as CVE-2008-2933, CVE-2008-2785, CVE-2008-2811, CVE-2008-2810,
  CVE-2008-2809, CVE-2008-2808, CVE-2008-2807, CVE-2008-2806, CVE-2008-2805,
  CVE-2008-2803, CVE-2008-2802, CVE-2008-2801, CVE-2008-2800, CVE-2008-2798.
* Drop 89_bz419350_attachment_306066 patch, merged upstream.
* Bump Standards-Version to 3.8.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ***** BEGIN LICENSE BLOCK *****
 
2
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
3
 *
 
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/
 
8
 *
 
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
 
12
 * License.
 
13
 *
 
14
 * The Original Code is the Netscape security libraries.
 
15
 *
 
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
 
21
 *
 
22
 * Contributor(s):
 
23
 *   Bob Relyea (rrelyea@redhat.com)
 
24
 *
 
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.
 
36
 *
 
37
 * ***** END LICENSE BLOCK ***** */
 
38
#ifdef DEBUG
 
39
static const char CVS_ID[] = "@(#) $RCSfile: cobject.c,v $ $Revision: 1.4 $ $Date: 2005/11/16 01:17:25 $";
 
40
#endif /* DEBUG */
 
41
 
 
42
#include "ckcapi.h"
 
43
#include "nssbase.h"
 
44
 
 
45
/*
 
46
 * ckcapi/cobject.c
 
47
 *
 
48
 * This file implements the NSSCKMDObject object for the
 
49
 * "nss to capi objects" cryptoki module.
 
50
 */
 
51
 
 
52
const CK_ATTRIBUTE_TYPE certAttrs[] = {
 
53
    CKA_CLASS,
 
54
    CKA_TOKEN,
 
55
    CKA_PRIVATE,
 
56
    CKA_MODIFIABLE,
 
57
    CKA_LABEL,
 
58
    CKA_CERTIFICATE_TYPE,
 
59
    CKA_SUBJECT,
 
60
    CKA_ISSUER,
 
61
    CKA_SERIAL_NUMBER,
 
62
    CKA_VALUE
 
63
};
 
64
const PRUint32 certAttrsCount = NSS_CKCAPI_ARRAY_SIZE(certAttrs);
 
65
 
 
66
/* private keys, for now only support RSA */
 
67
const CK_ATTRIBUTE_TYPE privKeyAttrs[] = {
 
68
    CKA_CLASS,
 
69
    CKA_TOKEN,
 
70
    CKA_PRIVATE,
 
71
    CKA_MODIFIABLE,
 
72
    CKA_LABEL,
 
73
    CKA_KEY_TYPE,
 
74
    CKA_DERIVE,
 
75
    CKA_LOCAL,
 
76
    CKA_SUBJECT,
 
77
    CKA_SENSITIVE,
 
78
    CKA_DECRYPT,
 
79
    CKA_SIGN,
 
80
    CKA_SIGN_RECOVER,
 
81
    CKA_UNWRAP,
 
82
    CKA_EXTRACTABLE,
 
83
    CKA_ALWAYS_SENSITIVE,
 
84
    CKA_NEVER_EXTRACTABLE,
 
85
    CKA_MODULUS,
 
86
    CKA_PUBLIC_EXPONENT,
 
87
};
 
88
const PRUint32 privKeyAttrsCount = NSS_CKCAPI_ARRAY_SIZE(privKeyAttrs);
 
89
 
 
90
/* public keys, for now only support RSA */
 
91
const CK_ATTRIBUTE_TYPE pubKeyAttrs[] = {
 
92
    CKA_CLASS,
 
93
    CKA_TOKEN,
 
94
    CKA_PRIVATE,
 
95
    CKA_MODIFIABLE,
 
96
    CKA_LABEL,
 
97
    CKA_KEY_TYPE,
 
98
    CKA_DERIVE,
 
99
    CKA_LOCAL,
 
100
    CKA_SUBJECT,
 
101
    CKA_ENCRYPT,
 
102
    CKA_VERIFY,
 
103
    CKA_VERIFY_RECOVER,
 
104
    CKA_WRAP,
 
105
    CKA_MODULUS,
 
106
    CKA_PUBLIC_EXPONENT,
 
107
};
 
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};
 
132
 
 
133
/*
 
134
 * these are utilities. The chould be moved to a new utilities file.
 
135
 */
 
136
 
 
137
/*
 
138
 * unwrap a single DER value
 
139
 */
 
140
char *
 
141
nss_ckcapi_DERUnwrap
 
142
(
 
143
  char *src, 
 
144
  int size, 
 
145
  int *outSize, 
 
146
  char **next
 
147
)
 
148
{
 
149
  unsigned char *start = src;
 
150
  unsigned char *end = src+size;
 
151
  unsigned int len = 0;
 
152
 
 
153
  /* initialize error condition return values */
 
154
  *outSize = 0;
 
155
  if (next) {
 
156
    *next = src;
 
157
  }
 
158
 
 
159
  if (size < 2) {
 
160
    return start;
 
161
  }
 
162
  src ++ ; /* skip the tag -- should check it against an expected value! */
 
163
  len = (unsigned) *src++;
 
164
  if (len & 0x80) {
 
165
    int count = len & 0x7f;
 
166
    len =0;
 
167
 
 
168
    if (count+2 > size) {
 
169
      return start;
 
170
    }
 
171
    while (count-- > 0) {
 
172
      len = (len << 8) | (unsigned) *src++;
 
173
    }
 
174
  }
 
175
  if (len + (src-start) > (unsigned int)size) {
 
176
    return start;
 
177
  }
 
178
  if (next) {
 
179
    *next = src+len;
 
180
  }
 
181
  *outSize = len;
 
182
 
 
183
  return src;
 
184
}
 
185
 
 
186
/*
 
187
 * convert a PKCS #11 bytestrin into a CK_ULONG, the byte stream must be
 
188
 * less than sizeof (CK_ULONG).
 
189
 */
 
190
CK_ULONG  
 
191
nss_ckcapi_DataToInt
 
192
(
 
193
  NSSItem *data,
 
194
  CK_RV *pError
 
195
)
 
196
{
 
197
  CK_ULONG value = 0;
 
198
  unsigned long count = data->size;
 
199
  unsigned char *dataPtr = data->data;
 
200
  unsigned long size = 0;
 
201
 
 
202
  *pError = CKR_OK;
 
203
 
 
204
  while (count--) {
 
205
    value = value << 8;
 
206
    value = value + *dataPtr++;
 
207
    if (size || value) {
 
208
      size++;
 
209
    }
 
210
  }
 
211
  if (size > sizeof(CK_ULONG)) {
 
212
    *pError = CKR_ATTRIBUTE_VALUE_INVALID;
 
213
  }
 
214
  return value;
 
215
}
 
216
 
 
217
/*
 
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.
 
220
 */
 
221
CK_ULONG  
 
222
nss_ckcapi_IntToData
 
223
(
 
224
  CK_ULONG value,
 
225
  NSSItem *data,
 
226
  unsigned char *dataPtr,
 
227
  CK_RV *pError
 
228
)
 
229
{
 
230
  unsigned long count = 0;
 
231
  unsigned long i;
 
232
#define SHIFT ((sizeof(CK_ULONG)-1)*8)
 
233
  PRBool first = 0;
 
234
 
 
235
  *pError = CKR_OK;
 
236
 
 
237
  data->data = dataPtr;
 
238
  for (i=0; i < sizeof(CK_ULONG); i++) {
 
239
    unsigned char digit = (unsigned char)((value >> SHIFT) & 0xff);
 
240
 
 
241
    value = value << 8;
 
242
 
 
243
    /* drop leading zero bytes */
 
244
    if (first && (0 == digit)) {
 
245
        continue;
 
246
    }
 
247
    *dataPtr++ = digit;
 
248
    count++;
 
249
  }
 
250
  data->size = count;
 
251
  return count;
 
252
}
 
253
 
 
254
/*
 
255
 * get an attribute from a template. Value is returned in NSS item.
 
256
 * data for the item is owned by the template.
 
257
 */
 
258
CK_RV
 
259
nss_ckcapi_GetAttribute
 
260
(
 
261
  CK_ATTRIBUTE_TYPE type,
 
262
  CK_ATTRIBUTE *template,
 
263
  CK_ULONG templateSize, 
 
264
  NSSItem *item
 
265
)
 
266
{
 
267
  CK_ULONG i;
 
268
 
 
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;
 
273
      return CKR_OK;
 
274
    }
 
275
  }
 
276
  return CKR_TEMPLATE_INCOMPLETE;
 
277
}
 
278
 
 
279
/*
 
280
 * get an attribute which is type CK_ULONG.
 
281
 */
 
282
CK_ULONG
 
283
nss_ckcapi_GetULongAttribute
 
284
(
 
285
  CK_ATTRIBUTE_TYPE type,
 
286
  CK_ATTRIBUTE *template,
 
287
  CK_ULONG templateSize, 
 
288
  CK_RV *pError
 
289
)
 
290
{
 
291
  NSSItem item;
 
292
 
 
293
  *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item);
 
294
  if (CKR_OK != *pError) {
 
295
    return (CK_ULONG) 0;
 
296
  }
 
297
  if (item.size != sizeof(CK_ULONG)) {
 
298
    *pError = CKR_ATTRIBUTE_VALUE_INVALID;
 
299
    return (CK_ULONG) 0;
 
300
  }
 
301
  return *(CK_ULONG *)item.data;
 
302
}
 
303
 
 
304
/*
 
305
 * get an attribute which is type CK_BBOOL.
 
306
 */
 
307
CK_BBOOL
 
308
nss_ckcapi_GetBoolAttribute
 
309
(
 
310
  CK_ATTRIBUTE_TYPE type,
 
311
  CK_ATTRIBUTE *template,
 
312
  CK_ULONG templateSize, 
 
313
  CK_RV *pError
 
314
)
 
315
{
 
316
  NSSItem item;
 
317
 
 
318
  *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item);
 
319
  if (CKR_OK != *pError) {
 
320
    return (CK_BBOOL) 0;
 
321
  }
 
322
  if (item.size != sizeof(CK_BBOOL)) {
 
323
    *pError = CKR_ATTRIBUTE_VALUE_INVALID;
 
324
    return (CK_BBOOL) 0;
 
325
  }
 
326
  return *(CK_BBOOL *)item.data;
 
327
}
 
328
 
 
329
/*
 
330
 * get an attribute which is type CK_BBOOL.
 
331
 */
 
332
char *
 
333
nss_ckcapi_GetStringAttribute
 
334
(
 
335
  CK_ATTRIBUTE_TYPE type,
 
336
  CK_ATTRIBUTE *template,
 
337
  CK_ULONG templateSize, 
 
338
  CK_RV *pError
 
339
)
 
340
{
 
341
  NSSItem item;
 
342
  char *str;
 
343
 
 
344
  /* get the attribute */
 
345
  *pError = nss_ckcapi_GetAttribute(type, template, templateSize, &item);
 
346
  if (CKR_OK != *pError) {
 
347
    return (char *)NULL;
 
348
  }
 
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;
 
353
    return (char *)NULL;
 
354
  }
 
355
 
 
356
  nsslibc_memcpy(str, item.data, item.size);
 
357
  str[item.size] = 0;
 
358
 
 
359
  return str;
 
360
}
 
361
 
 
362
/*
 
363
 * Return the size in bytes of a wide string
 
364
 */
 
365
int
 
366
nss_ckcapi_WideSize
 
367
(
 
368
  LPCWSTR wide
 
369
)
 
370
{
 
371
  DWORD size;
 
372
 
 
373
  if ((LPWSTR)NULL == wide) {
 
374
    return 0;
 
375
  }
 
376
  size = wcslen(wide)+1;
 
377
  return size*2;
 
378
}
 
379
 
 
380
/*
 
381
 * Covert a Unicode wide character string to a UTF8 string
 
382
 */
 
383
char *
 
384
nss_ckcapi_WideToUTF8
 
385
(
 
386
  LPCWSTR wide 
 
387
)
 
388
{
 
389
  DWORD len;
 
390
  DWORD size;
 
391
  char *buf;
 
392
 
 
393
  if ((LPWSTR)NULL == wide) {
 
394
    return (char *)NULL;
 
395
  }
 
396
 
 
397
  len = nss_ckcapi_WideSize(wide);
 
398
 
 
399
  size = WideCharToMultiByte(CP_UTF8, 0, wide, len, NULL, 0, NULL, 0);
 
400
  if (size == 0) {
 
401
    return (char *)NULL;
 
402
  }
 
403
  buf = nss_ZNEWARRAY(NULL, char, size);
 
404
  size = WideCharToMultiByte(CP_UTF8, 0, wide, len, buf, size, NULL, 0);
 
405
  if (size == 0) {
 
406
    nss_ZFreeIf(buf);
 
407
    return (char *)NULL;
 
408
  }
 
409
  return buf;
 
410
}
 
411
 
 
412
/*
 
413
 * Return a Wide String duplicated with nss allocated memory.
 
414
 */
 
415
LPWSTR
 
416
nss_ckcapi_WideDup
 
417
(
 
418
  LPCWSTR wide
 
419
)
 
420
{
 
421
  DWORD len = nss_ckcapi_WideSize(wide);
 
422
  LPWSTR buf;
 
423
 
 
424
  if ((LPWSTR)NULL == wide) {
 
425
    return (LPWSTR)NULL;
 
426
  }
 
427
 
 
428
  len = nss_ckcapi_WideSize(wide);
 
429
 
 
430
  buf = (LPWSTR) nss_ZNEWARRAY(NULL, char, len);
 
431
  if ((LPWSTR) NULL == buf) {
 
432
    return buf;
 
433
  }
 
434
  nsslibc_memcpy(buf, wide, len);
 
435
  return buf;
 
436
}
 
437
 
 
438
/*
 
439
 * Covert a UTF8 string to Unicode wide character
 
440
 */
 
441
LPWSTR
 
442
nss_ckcapi_UTF8ToWide
 
443
(
 
444
  char *buf
 
445
)
 
446
{
 
447
  DWORD size;
 
448
  DWORD len = strlen(buf)+1;
 
449
  LPWSTR wide;
 
450
 
 
451
  if ((char *)NULL == buf) {
 
452
    return (LPWSTR) NULL;
 
453
  }
 
454
    
 
455
  len = strlen(buf)+1;
 
456
 
 
457
  size = MultiByteToWideChar(CP_UTF8, 0, buf, len, NULL, 0);
 
458
  if (size == 0) {
 
459
    return (LPWSTR) NULL;
 
460
  }
 
461
  wide = nss_ZNEWARRAY(NULL, WCHAR, size);
 
462
  size = MultiByteToWideChar(CP_UTF8, 0, buf, len, wide, size);
 
463
  if (size == 0) {
 
464
    nss_ZFreeIf(wide);
 
465
    return (LPWSTR) NULL;
 
466
  }
 
467
  return wide;
 
468
}
 
469
 
 
470
 
 
471
/*
 
472
 * keep all the knowlege of how the internalObject is laid out in this function
 
473
 *
 
474
 * nss_ckcapi_FetchKeyContainer
 
475
 *
 
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
 
479
 */
 
480
NSS_EXTERN CK_RV
 
481
nss_ckcapi_FetchKeyContainer
 
482
(
 
483
  ckcapiInternalObject *iKey,
 
484
  HCRYPTPROV *hProv, 
 
485
  DWORD *keySpec,
 
486
  HCRYPTKEY *hKey
 
487
)
 
488
{
 
489
  ckcapiCertObject *co;
 
490
  ckcapiKeyObject *ko;
 
491
  BOOL rc, dummy;
 
492
  DWORD msError;
 
493
 
 
494
 
 
495
  switch (iKey->type) {
 
496
  default:
 
497
  case ckcapiRaw:
 
498
     /* can't have raw private keys */
 
499
     return CKR_KEY_TYPE_INCONSISTENT;
 
500
  case ckcapiCert:
 
501
    if (iKey->objClass != CKO_PRIVATE_KEY) {
 
502
      /* Only private keys have private key provider handles */
 
503
      return CKR_KEY_TYPE_INCONSISTENT;
 
504
    }
 
505
    co = &iKey->u.cert;
 
506
 
 
507
    /* OK, get the Provider */
 
508
    rc = CryptAcquireCertificatePrivateKey(co->certContext,
 
509
      CRYPT_ACQUIRE_CACHE_FLAG|CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, hProv, 
 
510
      keySpec, &dummy);
 
511
    if (!rc) {
 
512
      goto loser;
 
513
    }
 
514
    break;
 
515
  case ckcapiBareKey:
 
516
    if (iKey->objClass != CKO_PRIVATE_KEY) {
 
517
       /* Only private keys have private key provider handles */
 
518
       return CKR_KEY_TYPE_INCONSISTENT;
 
519
    }
 
520
    ko = &iKey->u.key;
 
521
 
 
522
    /* OK, get the Provider */
 
523
    if (0 == ko->hProv) {
 
524
      rc = CryptAcquireContext(hProv,
 
525
                               ko->containerName, 
 
526
                               ko->provName,
 
527
                               ko->provInfo.dwProvType , 0);
 
528
      if (!rc) {
 
529
        goto loser;
 
530
      }
 
531
    } else {
 
532
      *hProv = ko->hProv;
 
533
    }
 
534
    *keySpec = ko->provInfo.dwKeySpec;
 
535
    break;
 
536
  }
 
537
 
 
538
  /* and get the crypto handle */
 
539
  rc = CryptGetUserKey(*hProv, *keySpec, hKey);
 
540
  if (!rc) {
 
541
    goto loser;
 
542
  }
 
543
  return CKR_OK;
 
544
loser:
 
545
  /* map the microsoft error before leaving */
 
546
  msError = GetLastError();
 
547
  switch (msError) {
 
548
  case ERROR_INVALID_HANDLE:
 
549
  case ERROR_INVALID_PARAMETER:
 
550
  case NTE_BAD_KEY:
 
551
  case NTE_NO_KEY:
 
552
  case NTE_BAD_PUBLIC_KEY:
 
553
  case NTE_BAD_KEYSET:
 
554
  case NTE_KEYSET_NOT_DEF:
 
555
    return CKR_KEY_TYPE_INCONSISTENT;
 
556
  case NTE_BAD_UID:
 
557
  case NTE_KEYSET_ENTRY_BAD:
 
558
    return CKR_DEVICE_ERROR;
 
559
  }
 
560
  return CKR_GENERAL_ERROR;
 
561
}
 
562
 
 
563
 
 
564
/*
 
565
 * take a DER PUBLIC Key block and return the modulus and exponent
 
566
 */
 
567
static void
 
568
ckcapi_CertPopulateModulusExponent
 
569
(
 
570
  ckcapiInternalObject *io
 
571
)
 
572
{
 
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;
 
577
  CK_ULONG newSize;
 
578
  char *ptr, *newptr;
 
579
 
 
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;
 
589
  }
 
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;
 
596
  }
 
597
  return;
 
598
}
 
599
 
 
600
typedef struct _CAPI_RSA_KEY_BLOB {
 
601
  PUBLICKEYSTRUC header;
 
602
  RSAPUBKEY  rsa;
 
603
  char       data[1];
 
604
} CAPI_RSA_KEY_BLOB;
 
605
 
 
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)
 
613
 
 
614
void
 
615
ckcapi_FetchPublicKey
 
616
(
 
617
  ckcapiInternalObject *io
 
618
)
 
619
{
 
620
  ckcapiKeyParams *kp;
 
621
  HCRYPTPROV hProv;
 
622
  DWORD keySpec;
 
623
  HCRYPTKEY hKey = 0;
 
624
  CK_RV error;
 
625
  DWORD bufLen;
 
626
  BOOL rc;
 
627
  unsigned long modulus;
 
628
  char *buf = NULL;
 
629
  CAPI_RSA_KEY_BLOB *blob;
 
630
 
 
631
  error = nss_ckcapi_FetchKeyContainer(io, &hProv, &keySpec, &hKey);
 
632
  if (CKR_OK != error) {
 
633
    goto loser;
 
634
  }
 
635
  kp = (ckcapiCert == io->type) ?  &io->u.cert.key : &io->u.key.key;
 
636
 
 
637
  rc = CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, buf, &bufLen);
 
638
  if (!rc) {
 
639
    goto loser;
 
640
  }
 
641
  buf = nss_ZNEWARRAY(NULL, char, bufLen);
 
642
  rc = CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, buf, &bufLen);
 
643
  if (!rc) {
 
644
    goto loser;
 
645
  }
 
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)) {
 
651
    goto loser;
 
652
  }
 
653
  modulus = blob->rsa.bitlen/8;
 
654
  kp->pubKey = buf;
 
655
  buf = NULL;
 
656
 
 
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);
 
662
 
 
663
loser:
 
664
  nss_ZFreeIf(buf);
 
665
  if (0 != hKey) {
 
666
     CryptDestroyKey(hKey);
 
667
  }
 
668
  return;
 
669
}
 
670
 
 
671
void
 
672
ckcapi_FetchPrivateKey
 
673
(
 
674
  ckcapiInternalObject *io
 
675
)
 
676
{
 
677
  ckcapiKeyParams *kp;
 
678
  HCRYPTPROV hProv;
 
679
  DWORD keySpec;
 
680
  HCRYPTKEY hKey = 0;
 
681
  CK_RV error;
 
682
  DWORD bufLen;
 
683
  BOOL rc;
 
684
  unsigned long modulus;
 
685
  char *buf = NULL;
 
686
  CAPI_RSA_KEY_BLOB *blob;
 
687
 
 
688
  error = nss_ckcapi_FetchKeyContainer(io, &hProv, &keySpec, &hKey);
 
689
  if (CKR_OK != error) {
 
690
    goto loser;
 
691
  }
 
692
  kp = (ckcapiCert == io->type) ?  &io->u.cert.key : &io->u.key.key;
 
693
 
 
694
  rc = CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, buf, &bufLen);
 
695
  if (!rc) {
 
696
    goto loser;
 
697
  }
 
698
  buf = nss_ZNEWARRAY(NULL, char, bufLen);
 
699
  rc = CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, buf, &bufLen);
 
700
  if (!rc) {
 
701
    goto loser;
 
702
  }
 
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)) {
 
708
    goto loser;
 
709
  }
 
710
  modulus = blob->rsa.bitlen/8;
 
711
  kp->privateKey = buf;
 
712
  buf = NULL;
 
713
 
 
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);
 
732
 
 
733
loser:
 
734
  nss_ZFreeIf(buf);
 
735
  if (0 != hKey) {
 
736
     CryptDestroyKey(hKey);
 
737
  }
 
738
  return;
 
739
}
 
740
 
 
741
 
 
742
void
 
743
ckcapi_PopulateModulusExponent
 
744
(
 
745
  ckcapiInternalObject *io
 
746
)
 
747
{
 
748
  if (ckcapiCert == io->type) {
 
749
    ckcapi_CertPopulateModulusExponent(io);
 
750
  } else {
 
751
    ckcapi_FetchPublicKey(io);
 
752
  } 
 
753
  return;
 
754
}
 
755
 
 
756
/*
 
757
 * fetch the friendly name attribute.
 
758
 * can only be called with ckcapiCert type objects!
 
759
 */
 
760
void
 
761
ckcapi_FetchLabel
 
762
(
 
763
  ckcapiInternalObject *io
 
764
)
 
765
{
 
766
  ckcapiCertObject *co = &io->u.cert;
 
767
  char *label;
 
768
  PCCERT_CONTEXT certContext = io->u.cert.certContext;
 
769
  char labelDataUTF16[128];
 
770
  DWORD size = sizeof(labelDataUTF16);
 
771
  DWORD size8 = sizeof(co->labelData);
 
772
  BOOL rv;
 
773
 
 
774
  rv = CertGetCertificateContextProperty(certContext,
 
775
        CERT_FRIENDLY_NAME_PROP_ID, labelDataUTF16, &size);
 
776
  if (rv) {
 
777
    co->labelData = nss_ckcapi_WideToUTF8((LPCWSTR)labelDataUTF16);
 
778
    if ((CHAR *)NULL == co->labelData) {
 
779
      rv = 0;
 
780
    } else {
 
781
      size = strlen(co->labelData);
 
782
    }
 
783
  }
 
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);
 
792
    rv = 1;
 
793
  }
 
794
    
 
795
  if (rv) {
 
796
    co->label.data = label;
 
797
    co->label.size = size;
 
798
  }
 
799
  return;
 
800
}
 
801
 
 
802
void
 
803
ckcapi_FetchSerial
 
804
(
 
805
  ckcapiInternalObject *io
 
806
)
 
807
{
 
808
  ckcapiCertObject *co = &io->u.cert;
 
809
  PCCERT_CONTEXT certContext = io->u.cert.certContext;
 
810
  DWORD size = sizeof(co->derSerial);
 
811
 
 
812
  BOOL rc = CryptEncodeObject(X509_ASN_ENCODING,
 
813
                         X509_MULTI_BYTE_INTEGER,
 
814
                         &certContext->pCertInfo->SerialNumber,
 
815
                         co->derSerial,
 
816
                         &size);
 
817
  if (rc) {
 
818
    co->serial.data = co->derSerial;
 
819
    co->serial.size = size;
 
820
  }
 
821
  return;
 
822
}
 
823
 
 
824
/*
 
825
 * fetch the key ID.
 
826
 */
 
827
void
 
828
ckcapi_FetchID
 
829
(
 
830
  ckcapiInternalObject *io
 
831
)
 
832
{
 
833
  PCCERT_CONTEXT certContext = io->u.cert.certContext;
 
834
  DWORD size = 0;
 
835
  BOOL rc;
 
836
 
 
837
  rc = CertGetCertificateContextProperty(certContext,
 
838
        CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
 
839
  if (!rc) {
 
840
    return;
 
841
  }
 
842
  io->idData = nss_ZNEWARRAY(NULL, char, size);
 
843
  if (io->idData == NULL) {
 
844
    return;
 
845
  }
 
846
 
 
847
  rc = CertGetCertificateContextProperty(certContext,
 
848
        CERT_KEY_IDENTIFIER_PROP_ID, io->idData, &size);
 
849
  if (!rc) {
 
850
    nss_ZFreeIf(io->idData);
 
851
    io->idData = NULL;
 
852
    return;
 
853
  }
 
854
  io->id.data = io->idData;
 
855
  io->id.size = size;
 
856
  return;
 
857
}
 
858
 
 
859
/*
 
860
 * fetch the hash key.
 
861
 */
 
862
void
 
863
ckcapi_CertFetchHashKey
 
864
(
 
865
  ckcapiInternalObject *io
 
866
)
 
867
{
 
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;
 
872
  DWORD offset = 0;
 
873
 
 
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 */
 
876
  if (size > max) {
 
877
    offset = size - max;
 
878
    size = max;
 
879
  }
 
880
 
 
881
  nsslibc_memcpy(io->hashKeyData,certContext->pbCertEncoded+offset, size);
 
882
  io->hashKeyData[size] = (char)(io->objClass & 0xff);
 
883
 
 
884
  io->hashKey.data = io->hashKeyData;
 
885
  io->hashKey.size = size+1;
 
886
  return;
 
887
}
 
888
 
 
889
/*
 
890
 * fetch the hash key.
 
891
 */
 
892
void
 
893
ckcapi_KeyFetchHashKey
 
894
(
 
895
  ckcapiInternalObject *io
 
896
)
 
897
{
 
898
  ckcapiKeyObject *ko = &io->u.key;
 
899
  DWORD size;
 
900
  DWORD max = sizeof(io->hashKeyData)-2;
 
901
  DWORD offset = 0;
 
902
  DWORD provLen = strlen(ko->provName);
 
903
  DWORD containerLen = strlen(ko->containerName);
 
904
 
 
905
 
 
906
  size = provLen + containerLen; 
 
907
 
 
908
  /* make sure we don't overflow, try to keep things unique */
 
909
  if (size > max) {
 
910
    DWORD diff = ((size - max)+1)/2;
 
911
    provLen -= diff;
 
912
    containerLen -= diff;
 
913
    size = provLen+containerLen;
 
914
  }
 
915
 
 
916
  nsslibc_memcpy(io->hashKeyData, ko->provName, provLen);
 
917
  nsslibc_memcpy(&io->hashKeyData[provLen],
 
918
                 ko->containerName,
 
919
                 containerLen);
 
920
  io->hashKeyData[size] = (char)(io->objClass & 0xff);
 
921
  io->hashKeyData[size+1] = (char)(ko->provInfo.dwKeySpec & 0xff);
 
922
 
 
923
  io->hashKey.data = io->hashKeyData;
 
924
  io->hashKey.size = size+2;
 
925
  return;
 
926
}
 
927
 
 
928
/*
 
929
 * fetch the hash key.
 
930
 */
 
931
void
 
932
ckcapi_FetchHashKey
 
933
(
 
934
  ckcapiInternalObject *io
 
935
)
 
936
{
 
937
  if (ckcapiCert == io->type) {
 
938
    ckcapi_CertFetchHashKey(io);
 
939
  } else {
 
940
    ckcapi_KeyFetchHashKey(io);
 
941
  } 
 
942
  return;
 
943
}
 
944
 
 
945
const NSSItem *
 
946
ckcapi_FetchCertAttribute
 
947
(
 
948
  ckcapiInternalObject *io,
 
949
  CK_ATTRIBUTE_TYPE type
 
950
)
 
951
{
 
952
  PCCERT_CONTEXT certContext = io->u.cert.certContext;
 
953
  switch(type) {
 
954
  case CKA_CLASS:
 
955
    return &ckcapi_certClassItem;
 
956
  case CKA_TOKEN:
 
957
    return &ckcapi_trueItem;
 
958
  case CKA_MODIFIABLE:
 
959
  case CKA_PRIVATE:
 
960
    return &ckcapi_falseItem;
 
961
  case CKA_CERTIFICATE_TYPE:
 
962
    return &ckcapi_x509Item;
 
963
  case CKA_LABEL:
 
964
    if (0 == io->u.cert.label.size) {
 
965
      ckcapi_FetchLabel(io);
 
966
    }
 
967
    return &io->u.cert.label;
 
968
  case CKA_SUBJECT:
 
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;
 
972
    }
 
973
    return &io->u.cert.subject;
 
974
  case CKA_ISSUER:
 
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;
 
978
    }
 
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);
 
985
    }
 
986
    return &io->u.cert.serial;
 
987
  case CKA_VALUE:
 
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;
 
991
    }
 
992
    return &io->u.cert.derCert;
 
993
  case CKA_ID:
 
994
    if (!io->u.cert.hasID) {
 
995
      return NULL;
 
996
    }
 
997
    if (0 == io->id.size) {
 
998
      ckcapi_FetchID(io);
 
999
    }
 
1000
    return &io->id;
 
1001
  default:
 
1002
    break;
 
1003
  }
 
1004
  return NULL;
 
1005
}
 
1006
 
 
1007
const NSSItem *
 
1008
ckcapi_FetchPubKeyAttribute
 
1009
(
 
1010
  ckcapiInternalObject *io, 
 
1011
  CK_ATTRIBUTE_TYPE type
 
1012
)
 
1013
{
 
1014
  PRBool isCertType = (ckcapiCert == io->type);
 
1015
  ckcapiKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key;
 
1016
  
 
1017
  switch(type) {
 
1018
  case CKA_CLASS:
 
1019
    return &ckcapi_pubKeyClassItem;
 
1020
  case CKA_TOKEN:
 
1021
  case CKA_LOCAL:
 
1022
  case CKA_ENCRYPT:
 
1023
  case CKA_VERIFY:
 
1024
  case CKA_VERIFY_RECOVER:
 
1025
    return &ckcapi_trueItem;
 
1026
  case CKA_PRIVATE:
 
1027
  case CKA_MODIFIABLE:
 
1028
  case CKA_DERIVE:
 
1029
  case CKA_WRAP:
 
1030
    return &ckcapi_falseItem;
 
1031
  case CKA_KEY_TYPE:
 
1032
    return &ckcapi_rsaItem;
 
1033
  case CKA_LABEL:
 
1034
    if (!isCertType) {
 
1035
      return &ckcapi_emptyItem;
 
1036
    }
 
1037
    if (0 == io->u.cert.label.size) {
 
1038
      ckcapi_FetchLabel(io);
 
1039
    }
 
1040
    return &io->u.cert.label;
 
1041
  case CKA_SUBJECT:
 
1042
    if (!isCertType) {
 
1043
      return &ckcapi_emptyItem;
 
1044
    }
 
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;
 
1049
    }
 
1050
    return &io->u.cert.subject;
 
1051
  case CKA_MODULUS:
 
1052
    if (0 == kp->modulus.size) {
 
1053
        ckcapi_PopulateModulusExponent(io);
 
1054
    }
 
1055
    return &kp->modulus;
 
1056
  case CKA_PUBLIC_EXPONENT:
 
1057
    if (0 == kp->modulus.size) {
 
1058
        ckcapi_PopulateModulusExponent(io);
 
1059
    }
 
1060
    return &kp->exponent;
 
1061
  case CKA_ID:
 
1062
    if (0 == io->id.size) {
 
1063
      ckcapi_FetchID(io);
 
1064
    }
 
1065
    return &io->id;
 
1066
  default:
 
1067
    break;
 
1068
  }
 
1069
  return NULL;
 
1070
}
 
1071
 
 
1072
const NSSItem *
 
1073
ckcapi_FetchPrivKeyAttribute
 
1074
(
 
1075
  ckcapiInternalObject *io, 
 
1076
  CK_ATTRIBUTE_TYPE type
 
1077
)
 
1078
{
 
1079
  PRBool isCertType = (ckcapiCert == io->type);
 
1080
  ckcapiKeyParams *kp = isCertType ? &io->u.cert.key : &io->u.key.key;
 
1081
 
 
1082
  switch(type) {
 
1083
  case CKA_CLASS:
 
1084
    return &ckcapi_privKeyClassItem;
 
1085
  case CKA_TOKEN:
 
1086
  case CKA_LOCAL:
 
1087
  case CKA_SIGN:
 
1088
  case CKA_DECRYPT:
 
1089
  case CKA_SIGN_RECOVER:
 
1090
    return &ckcapi_trueItem;
 
1091
  case CKA_SENSITIVE:
 
1092
  case CKA_PRIVATE:    /* should move in the future */
 
1093
  case CKA_MODIFIABLE:
 
1094
  case CKA_DERIVE:
 
1095
  case CKA_UNWRAP:
 
1096
  case CKA_EXTRACTABLE: /* will probably move in the future */
 
1097
  case CKA_ALWAYS_SENSITIVE:
 
1098
  case CKA_NEVER_EXTRACTABLE:
 
1099
    return &ckcapi_falseItem;
 
1100
  case CKA_KEY_TYPE:
 
1101
    return &ckcapi_rsaItem;
 
1102
  case CKA_LABEL:
 
1103
    if (!isCertType) {
 
1104
      return &ckcapi_emptyItem;
 
1105
    }
 
1106
    if (0 == io->u.cert.label.size) {
 
1107
      ckcapi_FetchLabel(io);
 
1108
    }
 
1109
    return &io->u.cert.label;
 
1110
  case CKA_SUBJECT:
 
1111
    if (!isCertType) {
 
1112
      return &ckcapi_emptyItem;
 
1113
    }
 
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;
 
1118
    }
 
1119
    return &io->u.cert.subject;
 
1120
  case CKA_MODULUS:
 
1121
    if (0 == kp->modulus.size) {
 
1122
      ckcapi_PopulateModulusExponent(io);
 
1123
    }
 
1124
    return &kp->modulus;
 
1125
  case CKA_PUBLIC_EXPONENT:
 
1126
    if (0 == kp->modulus.size) {
 
1127
      ckcapi_PopulateModulusExponent(io);
 
1128
    }
 
1129
    return &kp->exponent;
 
1130
  case CKA_PRIVATE_EXPONENT:
 
1131
    if (0 == kp->privateExponent.size) {
 
1132
      ckcapi_FetchPrivateKey(io);
 
1133
    }
 
1134
    return &kp->privateExponent;
 
1135
  case CKA_PRIME_1:
 
1136
    if (0 == kp->privateExponent.size) {
 
1137
      ckcapi_FetchPrivateKey(io);
 
1138
    }
 
1139
    return &kp->prime1;
 
1140
  case CKA_PRIME_2:
 
1141
    if (0 == kp->privateExponent.size) {
 
1142
      ckcapi_FetchPrivateKey(io);
 
1143
    }
 
1144
    return &kp->prime2;
 
1145
  case CKA_EXPONENT_1:
 
1146
    if (0 == kp->privateExponent.size) {
 
1147
      ckcapi_FetchPrivateKey(io);
 
1148
    }
 
1149
    return &kp->exponent1;
 
1150
  case CKA_EXPONENT_2:
 
1151
    if (0 == kp->privateExponent.size) {
 
1152
      ckcapi_FetchPrivateKey(io);
 
1153
    }
 
1154
    return &kp->exponent2;
 
1155
  case CKA_COEFFICIENT:
 
1156
    if (0 == kp->privateExponent.size) {
 
1157
      ckcapi_FetchPrivateKey(io);
 
1158
    }
 
1159
    return &kp->coefficient;
 
1160
  case CKA_ID:
 
1161
    if (0 == io->id.size) {
 
1162
      ckcapi_FetchID(io);
 
1163
    }
 
1164
    return &io->id;
 
1165
  default:
 
1166
    return NULL;
 
1167
  }
 
1168
}
 
1169
 
 
1170
const NSSItem *
 
1171
nss_ckcapi_FetchAttribute
 
1172
(
 
1173
  ckcapiInternalObject *io, 
 
1174
  CK_ATTRIBUTE_TYPE type
 
1175
)
 
1176
{
 
1177
  CK_ULONG i;
 
1178
 
 
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];
 
1183
      }
 
1184
    }
 
1185
    return NULL;
 
1186
  }
 
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); 
 
1195
  }
 
1196
  return NULL;
 
1197
}
 
1198
 
 
1199
/*
 
1200
 * check to see if the certificate already exists
 
1201
 */
 
1202
static PRBool
 
1203
ckcapi_cert_exists(
 
1204
  NSSItem *value,
 
1205
  ckcapiInternalObject **io
 
1206
)
 
1207
{
 
1208
  int count,i;
 
1209
  PRUint32 size = 0;
 
1210
  ckcapiInternalObject **listp = NULL;
 
1211
  CK_ATTRIBUTE myTemplate[2];
 
1212
  CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE;
 
1213
  CK_ULONG templateCount = 2;
 
1214
  CK_RV error;
 
1215
  PRBool found = PR_FALSE;
 
1216
 
 
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;
 
1223
 
 
1224
  count = nss_ckcapi_collect_all_certs(myTemplate, templateCount, &listp, 
 
1225
                        &size, 0, &error);
 
1226
 
 
1227
  /* free them */
 
1228
  if (count > 1) {
 
1229
    *io = listp[0];
 
1230
    found = PR_TRUE;
 
1231
  }
 
1232
    
 
1233
  for (i=1; i < count; i++) {
 
1234
    nss_ckcapi_DestroyInternalObject(listp[i]);
 
1235
  }
 
1236
  nss_ZFreeIf(listp);
 
1237
  return found;
 
1238
}
 
1239
 
 
1240
static PRBool
 
1241
ckcapi_cert_hasEmail
 
1242
(
 
1243
  PCCERT_CONTEXT certContext
 
1244
)
 
1245
{
 
1246
  int count;
 
1247
 
 
1248
  count = CertGetNameString(certContext, CERT_NAME_EMAIL_TYPE, 
 
1249
                            0, NULL, NULL, 0);
 
1250
 
 
1251
  return count > 1 ? PR_TRUE : PR_FALSE;
 
1252
}
 
1253
 
 
1254
static PRBool
 
1255
ckcapi_cert_isRoot
 
1256
(
 
1257
  PCCERT_CONTEXT certContext
 
1258
)
 
1259
{
 
1260
  return CertCompareCertificateName(certContext->dwCertEncodingType,
 
1261
        &certContext->pCertInfo->Issuer, &certContext->pCertInfo->Subject);
 
1262
}
 
1263
 
 
1264
static PRBool
 
1265
ckcapi_cert_isCA
 
1266
(
 
1267
  PCCERT_CONTEXT certContext
 
1268
)
 
1269
{
 
1270
  PCERT_EXTENSION extension;
 
1271
  CERT_BASIC_CONSTRAINTS2_INFO basicInfo;
 
1272
  DWORD size = sizeof(basicInfo);
 
1273
  BOOL rc;
 
1274
 
 
1275
  extension = CertFindExtension (szOID_BASIC_CONSTRAINTS,
 
1276
                                certContext->pCertInfo->cExtension,
 
1277
                                certContext->pCertInfo->rgExtension);
 
1278
  if ((PCERT_EXTENSION) NULL == extension ) {
 
1279
    return PR_FALSE;
 
1280
  }
 
1281
  rc = CryptDecodeObject(X509_ASN_ENCODING, szOID_BASIC_CONSTRAINTS2,
 
1282
          extension->Value.pbData, extension->Value.cbData, 
 
1283
          0, &basicInfo, &size);
 
1284
  if (!rc) {
 
1285
    return PR_FALSE;
 
1286
  }
 
1287
  return (PRBool) basicInfo.fCA;
 
1288
}
 
1289
 
 
1290
static CRYPT_KEY_PROV_INFO *
 
1291
ckcapi_cert_getPrivateKeyInfo
 
1292
(
 
1293
  PCCERT_CONTEXT certContext,
 
1294
  NSSItem *keyID
 
1295
)
 
1296
{
 
1297
  BOOL rc;
 
1298
  CRYPT_HASH_BLOB msKeyID;
 
1299
  DWORD size = 0;
 
1300
  CRYPT_KEY_PROV_INFO *prov = NULL;
 
1301
 
 
1302
  msKeyID.cbData = keyID->size;
 
1303
  msKeyID.pbData = keyID->data;
 
1304
 
 
1305
  rc = CryptGetKeyIdentifierProperty(
 
1306
          &msKeyID,
 
1307
          CERT_KEY_PROV_INFO_PROP_ID,
 
1308
          0, NULL, NULL, NULL, &size);
 
1309
  if (!rc) {
 
1310
    return (CRYPT_KEY_PROV_INFO *)NULL;
 
1311
  }
 
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;
 
1315
  }
 
1316
  rc = CryptGetKeyIdentifierProperty(
 
1317
          &msKeyID,
 
1318
          CERT_KEY_PROV_INFO_PROP_ID,
 
1319
          0, NULL, NULL, prov, &size);
 
1320
  if (!rc) {
 
1321
    nss_ZFreeIf(prov);
 
1322
    return (CRYPT_KEY_PROV_INFO *)NULL;
 
1323
  }
 
1324
  
 
1325
  return prov;
 
1326
}
 
1327
 
 
1328
static CRYPT_KEY_PROV_INFO *
 
1329
ckcapi_cert_getProvInfo
 
1330
(
 
1331
  ckcapiInternalObject *io
 
1332
)
 
1333
{
 
1334
  BOOL rc;
 
1335
  DWORD size = 0;
 
1336
  CRYPT_KEY_PROV_INFO *prov = NULL;
 
1337
 
 
1338
  rc = CertGetCertificateContextProperty(
 
1339
          io->u.cert.certContext,
 
1340
          CERT_KEY_PROV_INFO_PROP_ID,
 
1341
          NULL, &size);
 
1342
  if (!rc) {
 
1343
    return (CRYPT_KEY_PROV_INFO *)NULL;
 
1344
  }
 
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;
 
1348
  }
 
1349
  rc = CertGetCertificateContextProperty(
 
1350
          io->u.cert.certContext,
 
1351
          CERT_KEY_PROV_INFO_PROP_ID,
 
1352
          prov, &size);
 
1353
  if (!rc) {
 
1354
    nss_ZFreeIf(prov);
 
1355
    return (CRYPT_KEY_PROV_INFO *)NULL;
 
1356
  }
 
1357
 
 
1358
  return prov;
 
1359
}
 
1360
  
 
1361
/* forward declaration */
 
1362
static void
 
1363
ckcapi_removeObjectFromHash
 
1364
(
 
1365
  ckcapiInternalObject *io
 
1366
);
 
1367
 
 
1368
/*
 
1369
 * Finalize - unneeded
 
1370
 * Destroy 
 
1371
 * IsTokenObject - CK_TRUE
 
1372
 * GetAttributeCount
 
1373
 * GetAttributeTypes
 
1374
 * GetAttributeSize
 
1375
 * GetAttribute
 
1376
 * SetAttribute
 
1377
 * GetObjectSize
 
1378
 */
 
1379
 
 
1380
static CK_RV
 
1381
ckcapi_mdObject_Destroy
 
1382
(
 
1383
  NSSCKMDObject *mdObject,
 
1384
  NSSCKFWObject *fwObject,
 
1385
  NSSCKMDSession *mdSession,
 
1386
  NSSCKFWSession *fwSession,
 
1387
  NSSCKMDToken *mdToken,
 
1388
  NSSCKFWToken *fwToken,
 
1389
  NSSCKMDInstance *mdInstance,
 
1390
  NSSCKFWInstance *fwInstance
 
1391
)
 
1392
{
 
1393
  ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
 
1394
  CK_OBJECT_CLASS objClass;
 
1395
  BOOL rc;
 
1396
  DWORD provType;
 
1397
  DWORD msError;
 
1398
  PRBool isCertType = (PRBool)(ckcapiCert == io->type);
 
1399
  HCERTSTORE hStore = 0;
 
1400
 
 
1401
  if (ckcapiRaw == io->type) {
 
1402
    /* there is not 'object write protected' error, use the next best thing */
 
1403
    return CKR_TOKEN_WRITE_PROTECTED;
 
1404
  }
 
1405
 
 
1406
  objClass = io->objClass;
 
1407
  if (CKO_CERTIFICATE == objClass) {
 
1408
    PCCERT_CONTEXT certContext;
 
1409
 
 
1410
    /* get the store */
 
1411
    hStore = CertOpenSystemStore(0, io->u.cert.certStore);
 
1412
    if (0 == hStore) {
 
1413
      rc = 0;
 
1414
      goto loser;
 
1415
    }
 
1416
    certContext = CertFindCertificateInStore(hStore, X509_ASN_ENCODING, 0, 
 
1417
      CERT_FIND_EXISTING, io->u.cert.certContext, NULL); 
 
1418
    if ((PCCERT_CONTEXT)NULL ==  certContext) {
 
1419
      rc = 0;
 
1420
      goto loser;
 
1421
    }
 
1422
    rc = CertDeleteCertificateFromStore(certContext);
 
1423
    CertFreeCertificateContext(certContext);
 
1424
  } else {
 
1425
    char *provName = NULL;
 
1426
    char *containerName = NULL;
 
1427
    HCRYPTPROV hProv;
 
1428
    CRYPT_HASH_BLOB msKeyID;
 
1429
 
 
1430
    if (0 == io->id.size) {
 
1431
      ckcapi_FetchID(io);
 
1432
    }
 
1433
 
 
1434
    if (isCertType) {
 
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);
 
1440
    } else {
 
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;
 
1446
    }
 
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);
 
1452
    if (rc) {
 
1453
      rc = CryptAcquireContext(&hProv, containerName, provName, provType,
 
1454
                CRYPT_DELETEKEYSET);
 
1455
    }
 
1456
    nss_ZFreeIf(provName);
 
1457
    nss_ZFreeIf(containerName);
 
1458
  }
 
1459
loser:
 
1460
 
 
1461
  if (hStore) {
 
1462
    CertCloseStore(hStore, 0);
 
1463
  }
 
1464
  if (!rc) {
 
1465
    msError = GetLastError();
 
1466
    return CKR_GENERAL_ERROR;
 
1467
  }
 
1468
 
 
1469
  /* remove it from the hash */
 
1470
  ckcapi_removeObjectFromHash(io);
 
1471
 
 
1472
  /* free the puppy.. */
 
1473
  nss_ckcapi_DestroyInternalObject(io);
 
1474
  return CKR_OK;
 
1475
}
 
1476
 
 
1477
static CK_BBOOL
 
1478
ckcapi_mdObject_IsTokenObject
 
1479
(
 
1480
  NSSCKMDObject *mdObject,
 
1481
  NSSCKFWObject *fwObject,
 
1482
  NSSCKMDSession *mdSession,
 
1483
  NSSCKFWSession *fwSession,
 
1484
  NSSCKMDToken *mdToken,
 
1485
  NSSCKFWToken *fwToken,
 
1486
  NSSCKMDInstance *mdInstance,
 
1487
  NSSCKFWInstance *fwInstance
 
1488
)
 
1489
{
 
1490
  return CK_TRUE;
 
1491
}
 
1492
 
 
1493
static CK_ULONG
 
1494
ckcapi_mdObject_GetAttributeCount
 
1495
(
 
1496
  NSSCKMDObject *mdObject,
 
1497
  NSSCKFWObject *fwObject,
 
1498
  NSSCKMDSession *mdSession,
 
1499
  NSSCKFWSession *fwSession,
 
1500
  NSSCKMDToken *mdToken,
 
1501
  NSSCKFWToken *fwToken,
 
1502
  NSSCKMDInstance *mdInstance,
 
1503
  NSSCKFWInstance *fwInstance,
 
1504
  CK_RV *pError
 
1505
)
 
1506
{
 
1507
  ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
 
1508
 
 
1509
  if (ckcapiRaw == io->type) {
 
1510
     return io->u.raw.n;
 
1511
  }
 
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;
 
1519
  default:
 
1520
    break;
 
1521
  }
 
1522
  return 0;
 
1523
}
 
1524
 
 
1525
static CK_RV
 
1526
ckcapi_mdObject_GetAttributeTypes
 
1527
(
 
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,
 
1537
  CK_ULONG ulCount
 
1538
)
 
1539
{
 
1540
  ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
 
1541
  CK_ULONG i;
 
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);
 
1547
 
 
1548
  if( size != ulCount ) {
 
1549
    return CKR_BUFFER_TOO_SMALL;
 
1550
  }
 
1551
  if (io->type == ckcapiRaw) {
 
1552
    attrs = io->u.raw.types;
 
1553
  } else switch(io->objClass) {
 
1554
    case CKO_CERTIFICATE:
 
1555
      attrs = certAttrs;
 
1556
      break;
 
1557
    case CKO_PUBLIC_KEY:
 
1558
      attrs = pubKeyAttrs;
 
1559
      break;
 
1560
    case CKO_PRIVATE_KEY:
 
1561
      attrs = privKeyAttrs;
 
1562
      break;
 
1563
    default:
 
1564
      return CKR_OK;
 
1565
  }
 
1566
  
 
1567
  for( i = 0; i < size; i++) {
 
1568
    typeArray[i] = attrs[i];
 
1569
  }
 
1570
 
 
1571
  return CKR_OK;
 
1572
}
 
1573
 
 
1574
static CK_ULONG
 
1575
ckcapi_mdObject_GetAttributeSize
 
1576
(
 
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,
 
1586
  CK_RV *pError
 
1587
)
 
1588
{
 
1589
  ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
 
1590
 
 
1591
  const NSSItem *b;
 
1592
 
 
1593
  b = nss_ckcapi_FetchAttribute(io, attribute);
 
1594
 
 
1595
  if ((const NSSItem *)NULL == b) {
 
1596
    *pError = CKR_ATTRIBUTE_TYPE_INVALID;
 
1597
    return 0;
 
1598
  }
 
1599
  return b->size;
 
1600
}
 
1601
 
 
1602
static CK_RV
 
1603
ckcapi_mdObject_SetAttribute
 
1604
(
 
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,
 
1614
  NSSItem           *value
 
1615
)
 
1616
{
 
1617
  return CKR_OK;
 
1618
}
 
1619
 
 
1620
static NSSCKFWItem
 
1621
ckcapi_mdObject_GetAttribute
 
1622
(
 
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,
 
1632
  CK_RV *pError
 
1633
)
 
1634
{
 
1635
  NSSCKFWItem mdItem;
 
1636
  ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
 
1637
 
 
1638
  mdItem.needsFreeing = PR_FALSE;
 
1639
  mdItem.item = (NSSItem*)nss_ckcapi_FetchAttribute(io, attribute);
 
1640
 
 
1641
  if ((NSSItem *)NULL == mdItem.item) {
 
1642
    *pError = CKR_ATTRIBUTE_TYPE_INVALID;
 
1643
  }
 
1644
 
 
1645
  return mdItem;
 
1646
}
 
1647
 
 
1648
static CK_ULONG
 
1649
ckcapi_mdObject_GetObjectSize
 
1650
(
 
1651
  NSSCKMDObject *mdObject,
 
1652
  NSSCKFWObject *fwObject,
 
1653
  NSSCKMDSession *mdSession,
 
1654
  NSSCKFWSession *fwSession,
 
1655
  NSSCKMDToken *mdToken,
 
1656
  NSSCKFWToken *fwToken,
 
1657
  NSSCKMDInstance *mdInstance,
 
1658
  NSSCKFWInstance *fwInstance,
 
1659
  CK_RV *pError
 
1660
)
 
1661
{
 
1662
  ckcapiInternalObject *io = (ckcapiInternalObject *)mdObject->etc;
 
1663
  CK_ULONG rv = 1;
 
1664
 
 
1665
  /* size is irrelevant to this token */
 
1666
  return rv;
 
1667
}
 
1668
 
 
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 */
 
1683
};
 
1684
 
 
1685
static nssHash *ckcapiInternalObjectHash = NULL;
 
1686
 
 
1687
NSS_IMPLEMENT NSSCKMDObject *
 
1688
nss_ckcapi_CreateMDObject
 
1689
(
 
1690
  NSSArena *arena,
 
1691
  ckcapiInternalObject *io,
 
1692
  CK_RV *pError
 
1693
)
 
1694
{
 
1695
  if ((nssHash *)NULL == ckcapiInternalObjectHash) {
 
1696
    ckcapiInternalObjectHash = nssHash_CreateItem(NULL, 10);
 
1697
  }
 
1698
  if (ckcapiCert == io->type) {
 
1699
    /* the hash key, not a cryptographic key */
 
1700
    NSSItem *key = &io->hashKey;
 
1701
    ckcapiInternalObject *old_o = NULL;
 
1702
 
 
1703
    if (key->size == 0) {
 
1704
      ckcapi_FetchHashKey(io);
 
1705
    }
 
1706
    old_o = (ckcapiInternalObject *) 
 
1707
              nssHash_Lookup(ckcapiInternalObjectHash, key);
 
1708
    if (!old_o) {
 
1709
      nssHash_Add(ckcapiInternalObjectHash, key, io);
 
1710
    } else if (old_o != io) {
 
1711
      nss_ckcapi_DestroyInternalObject(io);
 
1712
      io = old_o;
 
1713
    }
 
1714
  }
 
1715
    
 
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;
 
1720
  }
 
1721
  return &io->mdObject;
 
1722
}
 
1723
 
 
1724
static void
 
1725
ckcapi_removeObjectFromHash
 
1726
(
 
1727
  ckcapiInternalObject *io
 
1728
)
 
1729
{
 
1730
  NSSItem *key = &io->hashKey;
 
1731
 
 
1732
  if ((nssHash *)NULL == ckcapiInternalObjectHash) {
 
1733
    return;
 
1734
  }
 
1735
  if (key->size == 0) {
 
1736
    ckcapi_FetchHashKey(io);
 
1737
  }
 
1738
  nssHash_Remove(ckcapiInternalObjectHash, key);
 
1739
  return;
 
1740
}
 
1741
 
 
1742
void
 
1743
nss_ckcapi_DestroyInternalObject
 
1744
(
 
1745
  ckcapiInternalObject *io
 
1746
)
 
1747
{
 
1748
  switch (io->type) {
 
1749
  case ckcapiRaw:
 
1750
    return;
 
1751
  case ckcapiCert:
 
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);
 
1757
    break;
 
1758
  case ckcapiBareKey:
 
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);
 
1767
    }
 
1768
    nss_ZFreeIf(io->idData);
 
1769
    break;
 
1770
  }
 
1771
  nss_ZFreeIf(io);
 
1772
  return;
 
1773
}
 
1774
 
 
1775
static ckcapiInternalObject *
 
1776
nss_ckcapi_CreateCertificate
 
1777
(
 
1778
  NSSCKFWSession *fwSession,
 
1779
  CK_ATTRIBUTE_PTR pTemplate,
 
1780
  CK_ULONG ulAttributeCount,
 
1781
  CK_RV *pError
 
1782
)
 
1783
{
 
1784
  NSSItem value;
 
1785
  NSSItem keyID;
 
1786
  char *storeStr;
 
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;
 
1793
  DWORD msError = 0;
 
1794
  PRBool hasID;
 
1795
  CK_RV dummy;
 
1796
  BOOL rc;
 
1797
 
 
1798
  *pError = nss_ckcapi_GetAttribute(CKA_VALUE, pTemplate, 
 
1799
                                  ulAttributeCount, &value);
 
1800
 
 
1801
  if (CKR_OK != *pError) {
 
1802
    return (ckcapiInternalObject *)NULL;
 
1803
  }
 
1804
 
 
1805
  *pError = nss_ckcapi_GetAttribute(CKA_ID, pTemplate, 
 
1806
                                  ulAttributeCount, &keyID);
 
1807
 
 
1808
  if (CKR_OK != *pError) {
 
1809
    return (ckcapiInternalObject *)NULL;
 
1810
  }
 
1811
 
 
1812
  if (ckcapi_cert_exists(&value, &io)) {
 
1813
    return io;
 
1814
  }
 
1815
 
 
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;
 
1823
    goto loser;
 
1824
  }
 
1825
 
 
1826
  /* do we have a private key laying around... */
 
1827
  prov_info = ckcapi_cert_getPrivateKeyInfo(certContext, &keyID);
 
1828
  if (prov_info) {
 
1829
    CRYPT_DATA_BLOB msKeyID;
 
1830
    storeStr = "My";
 
1831
    hasID = PR_TRUE;
 
1832
    rc = CertSetCertificateContextProperty(certContext,
 
1833
                CERT_KEY_PROV_INFO_PROP_ID,
 
1834
                0, prov_info);
 
1835
    nss_ZFreeIf(prov_info);
 
1836
    if (!rc) {
 
1837
      msError = GetLastError();
 
1838
      *pError = CKR_DEVICE_ERROR;
 
1839
      goto loser;
 
1840
    }
 
1841
    msKeyID.cbData = keyID.size;
 
1842
    msKeyID.pbData = keyID.data;
 
1843
    rc = CertSetCertificateContextProperty(certContext,
 
1844
                CERT_KEY_IDENTIFIER_PROP_ID,
 
1845
                0, &msKeyID);
 
1846
    if (!rc) {
 
1847
      msError = GetLastError();
 
1848
      *pError = CKR_DEVICE_ERROR;
 
1849
      goto loser;
 
1850
    }
 
1851
    
 
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";
 
1858
  } else {
 
1859
  /* just pick a store */
 
1860
    storeStr = "CA";
 
1861
  }
 
1862
 
 
1863
  /* get the nickname, not an error if we can't find it */
 
1864
  nickname = nss_ckcapi_GetStringAttribute(CKA_LABEL, pTemplate, 
 
1865
                                  ulAttributeCount, &dummy);
 
1866
  if (nickname) {
 
1867
    LPWSTR nicknameUTF16 = NULL;
 
1868
    CRYPT_DATA_BLOB nicknameBlob;
 
1869
 
 
1870
    nicknameUTF16 = nss_ckcapi_UTF8ToWide(nickname);
 
1871
    nss_ZFreeIf(nickname);
 
1872
    nickname = NULL;
 
1873
    if ((LPWSTR)NULL == nicknameUTF16) {
 
1874
      *pError = CKR_HOST_MEMORY;
 
1875
      goto loser;
 
1876
    }
 
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);
 
1882
    if (!rc) {
 
1883
      msError = GetLastError();
 
1884
      *pError = CKR_DEVICE_ERROR;
 
1885
      goto loser;
 
1886
    }
 
1887
  }
 
1888
 
 
1889
  hStore = CertOpenSystemStore((HCRYPTPROV) NULL, storeStr);
 
1890
  if (0 == hStore) {
 
1891
    msError = GetLastError();
 
1892
    *pError = CKR_DEVICE_ERROR;
 
1893
    goto loser;
 
1894
  }
 
1895
 
 
1896
  rc = CertAddCertificateContextToStore(hStore, certContext, 
 
1897
       CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES, &storedCertContext);
 
1898
  CertFreeCertificateContext(certContext);
 
1899
  certContext = NULL;
 
1900
  CertCloseStore(hStore, 0);
 
1901
  hStore = 0;
 
1902
  if (!rc) {
 
1903
    msError = GetLastError();
 
1904
    *pError = CKR_DEVICE_ERROR;
 
1905
    goto loser;
 
1906
  }
 
1907
 
 
1908
  io = nss_ZNEW(NULL, ckcapiInternalObject);
 
1909
  if ((ckcapiInternalObject *)NULL == io) {
 
1910
    *pError = CKR_HOST_MEMORY;
 
1911
    goto loser;
 
1912
  }
 
1913
  io->type = ckcapiCert;
 
1914
  io->objClass = CKO_CERTIFICATE;
 
1915
  io->u.cert.certContext = storedCertContext;
 
1916
  io->u.cert.hasID = hasID;
 
1917
  return io;
 
1918
 
 
1919
loser:
 
1920
  if (certContext) {
 
1921
    CertFreeCertificateContext(certContext);
 
1922
    certContext = NULL;
 
1923
  }
 
1924
  if (storedCertContext) {
 
1925
    CertFreeCertificateContext(storedCertContext);
 
1926
    storedCertContext = NULL;
 
1927
  }
 
1928
  if (0 != hStore) {
 
1929
    CertCloseStore(hStore, 0);
 
1930
  }
 
1931
  return (ckcapiInternalObject *)NULL;
 
1932
 
 
1933
}
 
1934
 
 
1935
static char *
 
1936
ckcapi_getDefaultProvider
 
1937
(
 
1938
  CK_RV *pError
 
1939
)
 
1940
{
 
1941
  char *name = NULL;
 
1942
  BOOL rc;
 
1943
  DWORD nameLength = 0;
 
1944
 
 
1945
  rc = CryptGetDefaultProvider(PROV_RSA_FULL, NULL, CRYPT_USER_DEFAULT, NULL,
 
1946
                &nameLength);
 
1947
  if (!rc) {
 
1948
    return (char *)NULL;
 
1949
  }
 
1950
 
 
1951
  name = nss_ZNEWARRAY(NULL, char, nameLength);
 
1952
  if ((char *)NULL == name ) {
 
1953
    return (char *)NULL;
 
1954
  }
 
1955
  rc = CryptGetDefaultProvider(PROV_RSA_FULL, NULL, CRYPT_USER_DEFAULT, name,
 
1956
                &nameLength);
 
1957
  if (!rc) {
 
1958
    nss_ZFreeIf(name);
 
1959
    return (char *)NULL;
 
1960
  }
 
1961
 
 
1962
  return name;
 
1963
}
 
1964
 
 
1965
static char *
 
1966
ckcapi_getContainer
 
1967
(
 
1968
  CK_RV *pError,
 
1969
  NSSItem *id
 
1970
)
 
1971
{
 
1972
  RPC_STATUS rstat;
 
1973
  UUID uuid;
 
1974
  char *uuidStr;
 
1975
  char *container;
 
1976
 
 
1977
  rstat = UuidCreate(&uuid);
 
1978
  rstat = UuidToString(&uuid, &uuidStr);
 
1979
 
 
1980
  /* convert it from rcp memory to our own */
 
1981
  container = nssUTF8_Duplicate(uuidStr, NULL);
 
1982
  RpcStringFree(&uuidStr);
 
1983
  
 
1984
  return container;
 
1985
}
 
1986
 
 
1987
static CK_RV
 
1988
ckcapi_buildPrivateKeyBlob
 
1989
(
 
1990
  NSSItem  *keyBlob, 
 
1991
  NSSItem  *modulus,
 
1992
  NSSItem  *publicExponent,
 
1993
  NSSItem  *privateExponent,
 
1994
  NSSItem  *prime1,
 
1995
  NSSItem  *prime2,
 
1996
  NSSItem  *exponent1,
 
1997
  NSSItem  *exponent2,
 
1998
  NSSItem  *coefficient, 
 
1999
  PRBool   isKeyExchange
 
2000
)
 
2001
{
 
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;
 
2007
 
 
2008
  /* validate extras */
 
2009
  if (privateExponent->size != modSize) {
 
2010
    error = CKR_ATTRIBUTE_VALUE_INVALID;
 
2011
    goto loser;
 
2012
  }
 
2013
  if (prime1->size != modSize/2) {
 
2014
    error = CKR_ATTRIBUTE_VALUE_INVALID;
 
2015
    goto loser;
 
2016
  }
 
2017
  if (prime2->size != modSize/2) {
 
2018
    error = CKR_ATTRIBUTE_VALUE_INVALID;
 
2019
    goto loser;
 
2020
  }
 
2021
  if (exponent1->size != modSize/2) {
 
2022
    error = CKR_ATTRIBUTE_VALUE_INVALID;
 
2023
    goto loser;
 
2024
  }
 
2025
  if (exponent2->size != modSize/2) {
 
2026
    error = CKR_ATTRIBUTE_VALUE_INVALID;
 
2027
    goto loser;
 
2028
  }
 
2029
  if (coefficient->size != modSize/2) {
 
2030
    error = CKR_ATTRIBUTE_VALUE_INVALID;
 
2031
    goto loser;
 
2032
  }
 
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;
 
2037
    goto loser;
 
2038
  }
 
2039
 
 
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) {
 
2048
    goto loser;
 
2049
  }
 
2050
 
 
2051
  target = &keyBlobData->data[CAPI_MODULUS_OFFSET(modSize)];
 
2052
  nsslibc_memcpy(target, modulus->data, modulus->size);
 
2053
  modulus->data = target;
 
2054
  ckcapi_ReverseData(modulus);
 
2055
 
 
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);
 
2060
 
 
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);
 
2065
 
 
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);
 
2070
 
 
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);
 
2075
 
 
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);
 
2080
 
 
2081
  target = &keyBlobData->data[CAPI_COEFFICIENT_OFFSET(modSize)];
 
2082
  nsslibc_memcpy(target, coefficient->data, coefficient->size);
 
2083
  coefficient->data = target;
 
2084
  ckcapi_ReverseData(coefficient);
 
2085
 
 
2086
  keyBlob->data = keyBlobData;
 
2087
  keyBlob->size = dataSize;
 
2088
 
 
2089
  return CKR_OK;
 
2090
 
 
2091
loser:
 
2092
  nss_ZFreeIf(keyBlobData);
 
2093
  return error;
 
2094
}
 
2095
 
 
2096
static ckcapiInternalObject *
 
2097
nss_ckcapi_CreatePrivateKey
 
2098
(
 
2099
  NSSCKFWSession *fwSession,
 
2100
  CK_ATTRIBUTE_PTR pTemplate,
 
2101
  CK_ULONG ulAttributeCount,
 
2102
  CK_RV *pError
 
2103
)
 
2104
{
 
2105
  NSSItem modulus;
 
2106
  NSSItem publicExponent;
 
2107
  NSSItem privateExponent;
 
2108
  NSSItem exponent1;
 
2109
  NSSItem exponent2;
 
2110
  NSSItem prime1;
 
2111
  NSSItem prime2;
 
2112
  NSSItem coefficient;
 
2113
  NSSItem keyID;
 
2114
  NSSItem keyBlob;
 
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;
 
2123
  HCRYPTKEY hKey = 0;
 
2124
  PRBool decrypt;
 
2125
  DWORD keySpec;
 
2126
  DWORD msError;
 
2127
  BOOL rc;
 
2128
 
 
2129
  keyType = nss_ckcapi_GetULongAttribute
 
2130
                  (CKA_KEY_TYPE, pTemplate, ulAttributeCount, pError);
 
2131
  if (CKR_OK != *pError) {
 
2132
    return (ckcapiInternalObject *)NULL;
 
2133
  }
 
2134
  if (CKK_RSA != keyType) {
 
2135
    *pError = CKR_ATTRIBUTE_VALUE_INVALID;
 
2136
    return (ckcapiInternalObject *)NULL;
 
2137
  }
 
2138
 
 
2139
  decrypt = nss_ckcapi_GetBoolAttribute(CKA_DECRYPT, 
 
2140
                                pTemplate, ulAttributeCount, pError);
 
2141
  if (CKR_TEMPLATE_INCOMPLETE == *pError) {
 
2142
    decrypt = PR_TRUE; /* default to true */
 
2143
  }
 
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 */
 
2148
  }
 
2149
  keySpec = decrypt ? AT_KEYEXCHANGE : AT_SIGNATURE;
 
2150
 
 
2151
  *pError = nss_ckcapi_GetAttribute(CKA_MODULUS, pTemplate, 
 
2152
                                  ulAttributeCount, &modulus);
 
2153
  if (CKR_OK != *pError) {
 
2154
    return (ckcapiInternalObject *)NULL;
 
2155
  }
 
2156
  *pError = nss_ckcapi_GetAttribute(CKA_PUBLIC_EXPONENT, pTemplate, 
 
2157
                                  ulAttributeCount, &publicExponent);
 
2158
  if (CKR_OK != *pError) {
 
2159
    return (ckcapiInternalObject *)NULL;
 
2160
  }
 
2161
  *pError = nss_ckcapi_GetAttribute(CKA_PRIVATE_EXPONENT, pTemplate, 
 
2162
                                  ulAttributeCount, &privateExponent);
 
2163
  if (CKR_OK != *pError) {
 
2164
    return (ckcapiInternalObject *)NULL;
 
2165
  }
 
2166
  *pError = nss_ckcapi_GetAttribute(CKA_PRIME_1, pTemplate, 
 
2167
                                  ulAttributeCount, &prime1);
 
2168
  if (CKR_OK != *pError) {
 
2169
    return (ckcapiInternalObject *)NULL;
 
2170
  }
 
2171
  *pError = nss_ckcapi_GetAttribute(CKA_PRIME_2, pTemplate, 
 
2172
                                  ulAttributeCount, &prime2);
 
2173
  if (CKR_OK != *pError) {
 
2174
    return (ckcapiInternalObject *)NULL;
 
2175
  }
 
2176
  *pError = nss_ckcapi_GetAttribute(CKA_EXPONENT_1, pTemplate, 
 
2177
                                  ulAttributeCount, &exponent1);
 
2178
  if (CKR_OK != *pError) {
 
2179
    return (ckcapiInternalObject *)NULL;
 
2180
  }
 
2181
  *pError = nss_ckcapi_GetAttribute(CKA_EXPONENT_2, pTemplate, 
 
2182
                                  ulAttributeCount, &exponent2);
 
2183
  if (CKR_OK != *pError) {
 
2184
    return (ckcapiInternalObject *)NULL;
 
2185
  }
 
2186
  *pError = nss_ckcapi_GetAttribute(CKA_COEFFICIENT, pTemplate, 
 
2187
                                  ulAttributeCount, &coefficient);
 
2188
  if (CKR_OK != *pError) {
 
2189
    return (ckcapiInternalObject *)NULL;
 
2190
  }
 
2191
  *pError = nss_ckcapi_GetAttribute(CKA_ID, pTemplate, 
 
2192
                                  ulAttributeCount, &keyID);
 
2193
  if (CKR_OK != *pError) {
 
2194
    return (ckcapiInternalObject *)NULL;
 
2195
  }
 
2196
  providerName = ckcapi_getDefaultProvider(pError);
 
2197
  if ((char *)NULL == providerName ) {
 
2198
    return (ckcapiInternalObject *)NULL;
 
2199
  }
 
2200
  containerName = ckcapi_getContainer(pError, &keyID);
 
2201
  if ((char *)NULL == providerName ) {
 
2202
    goto loser;
 
2203
  }
 
2204
  rc = CryptAcquireContext(&hProv, containerName, providerName, 
 
2205
                           PROV_RSA_FULL, CRYPT_NEWKEYSET);
 
2206
  if (!rc) {
 
2207
    msError = GetLastError();
 
2208
    *pError = CKR_DEVICE_ERROR;
 
2209
    goto loser;
 
2210
  }
 
2211
 
 
2212
  *pError = ckcapi_buildPrivateKeyBlob(
 
2213
                &keyBlob, 
 
2214
                &modulus, 
 
2215
                &publicExponent, 
 
2216
                &privateExponent,
 
2217
                &prime1,
 
2218
                &prime2, 
 
2219
                &exponent1, 
 
2220
                &exponent2, 
 
2221
                &coefficient, 
 
2222
                decrypt);
 
2223
  if (CKR_OK != *pError) {
 
2224
    goto loser;
 
2225
  }
 
2226
 
 
2227
  rc = CryptImportKey(hProv, keyBlob.data, keyBlob.size, 
 
2228
                      0, CRYPT_EXPORTABLE, &hKey);
 
2229
  if (!rc) {
 
2230
    msError = GetLastError();
 
2231
    *pError = CKR_DEVICE_ERROR;
 
2232
    goto loser;
 
2233
  }
 
2234
 
 
2235
  idData = nss_ZNEWARRAY(NULL, char, keyID.size);
 
2236
  if ((void *)NULL == idData) {
 
2237
    *pError = CKR_HOST_MEMORY;
 
2238
    goto loser;
 
2239
  }
 
2240
  nsslibc_memcpy(idData, keyID.data, keyID.size);
 
2241
 
 
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;
 
2249
 
 
2250
  msKeyID.cbData = keyID.size;
 
2251
  msKeyID.pbData = keyID.data;
 
2252
 
 
2253
  rc = CryptSetKeyIdentifierProperty(&msKeyID, CERT_KEY_PROV_INFO_PROP_ID,
 
2254
                                     0, NULL, NULL, &provInfo);
 
2255
  if (!rc) {
 
2256
    goto loser;
 
2257
  }
 
2258
 
 
2259
  /* handle error here */
 
2260
  io = nss_ZNEW(NULL, ckcapiInternalObject);
 
2261
  if ((ckcapiInternalObject *)NULL == io) {
 
2262
    *pError = CKR_HOST_MEMORY;
 
2263
    goto loser;
 
2264
  }
 
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);
 
2276
  return io;
 
2277
 
 
2278
loser:
 
2279
  nss_ZFreeIf(containerName);
 
2280
  nss_ZFreeIf(providerName);
 
2281
  nss_ZFreeIf(idData);
 
2282
  if (0 != hProv) {
 
2283
    CryptReleaseContext(hProv, 0);
 
2284
  }
 
2285
  if (0 != hKey) {
 
2286
    CryptDestroyKey(hKey);
 
2287
  }
 
2288
  return (ckcapiInternalObject *)NULL;
 
2289
}
 
2290
 
 
2291
 
 
2292
NSS_EXTERN NSSCKMDObject *
 
2293
nss_ckcapi_CreateObject
 
2294
(
 
2295
  NSSCKFWSession *fwSession,
 
2296
  CK_ATTRIBUTE_PTR pTemplate,
 
2297
  CK_ULONG ulAttributeCount,
 
2298
  CK_RV *pError
 
2299
)
 
2300
{
 
2301
  CK_OBJECT_CLASS objClass;
 
2302
  ckcapiInternalObject *io;
 
2303
  CK_BBOOL isToken;
 
2304
 
 
2305
  /*
 
2306
   * only create token objects
 
2307
   */
 
2308
  isToken = nss_ckcapi_GetBoolAttribute(CKA_TOKEN, pTemplate, 
 
2309
                                        ulAttributeCount, pError);
 
2310
  if (CKR_OK != *pError) {
 
2311
    return (NSSCKMDObject *) NULL;
 
2312
  }
 
2313
  if (!isToken) {
 
2314
    *pError = CKR_ATTRIBUTE_VALUE_INVALID;
 
2315
    return (NSSCKMDObject *) NULL;
 
2316
  }
 
2317
 
 
2318
  /*
 
2319
   * only create keys and certs.
 
2320
   */
 
2321
  objClass = nss_ckcapi_GetULongAttribute(CKA_CLASS, pTemplate, 
 
2322
                                          ulAttributeCount, pError);
 
2323
  if (CKR_OK != *pError) {
 
2324
    return (NSSCKMDObject *) NULL;
 
2325
  }
 
2326
#ifdef notdef
 
2327
  if (objClass == CKO_PUBLIC_KEY) {
 
2328
    return CKR_OK; /* fake public key creation, happens as a side effect of
 
2329
                    * private key creation */
 
2330
  }
 
2331
#endif
 
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);
 
2338
  } else {
 
2339
    *pError = CKR_ATTRIBUTE_VALUE_INVALID;
 
2340
  }
 
2341
 
 
2342
  if ((ckcapiInternalObject *)NULL == io) {
 
2343
    return (NSSCKMDObject *) NULL;
 
2344
  }
 
2345
  return nss_ckcapi_CreateMDObject(NULL, io, pError);
 
2346
}