Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/lib/hx509/softp11.c
34878 views
1
/*
2
* Copyright (c) 2004 - 2008 Kungliga Tekniska Högskolan
3
* (Royal Institute of Technology, Stockholm, Sweden).
4
* All rights reserved.
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
*
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
*
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* 3. Neither the name of the Institute nor the names of its contributors
18
* may be used to endorse or promote products derived from this software
19
* without specific prior written permission.
20
*
21
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
* SUCH DAMAGE.
32
*/
33
34
#define CRYPTOKI_EXPORTS 1
35
36
#include "hx_locl.h"
37
#include "pkcs11.h"
38
39
#define OBJECT_ID_MASK 0xfff
40
#define HANDLE_OBJECT_ID(h) ((h) & OBJECT_ID_MASK)
41
#define OBJECT_ID(obj) HANDLE_OBJECT_ID((obj)->object_handle)
42
43
#ifndef HAVE_RANDOM
44
#define random() rand()
45
#define srandom(s) srand(s)
46
#endif
47
48
#ifdef _WIN32
49
#include <shlobj.h>
50
#endif
51
52
struct st_attr {
53
CK_ATTRIBUTE attribute;
54
int secret;
55
};
56
57
struct st_object {
58
CK_OBJECT_HANDLE object_handle;
59
struct st_attr *attrs;
60
int num_attributes;
61
hx509_cert cert;
62
};
63
64
static struct soft_token {
65
CK_VOID_PTR application;
66
CK_NOTIFY notify;
67
char *config_file;
68
hx509_certs certs;
69
struct {
70
struct st_object **objs;
71
int num_objs;
72
} object;
73
struct {
74
int hardware_slot;
75
int app_error_fatal;
76
int login_done;
77
} flags;
78
int open_sessions;
79
struct session_state {
80
CK_SESSION_HANDLE session_handle;
81
82
struct {
83
CK_ATTRIBUTE *attributes;
84
CK_ULONG num_attributes;
85
int next_object;
86
} find;
87
88
int sign_object;
89
CK_MECHANISM_PTR sign_mechanism;
90
int verify_object;
91
CK_MECHANISM_PTR verify_mechanism;
92
} state[10];
93
#define MAX_NUM_SESSION (sizeof(soft_token.state)/sizeof(soft_token.state[0]))
94
FILE *logfile;
95
} soft_token;
96
97
static hx509_context context;
98
99
static void
100
application_error(const char *fmt, ...)
101
{
102
va_list ap;
103
va_start(ap, fmt);
104
vprintf(fmt, ap);
105
va_end(ap);
106
if (soft_token.flags.app_error_fatal)
107
abort();
108
}
109
110
static void
111
st_logf(const char *fmt, ...)
112
{
113
va_list ap;
114
if (soft_token.logfile == NULL)
115
return;
116
va_start(ap, fmt);
117
vfprintf(soft_token.logfile, fmt, ap);
118
va_end(ap);
119
fflush(soft_token.logfile);
120
}
121
122
static CK_RV
123
init_context(void)
124
{
125
if (context == NULL) {
126
int ret = hx509_context_init(&context);
127
if (ret)
128
return CKR_GENERAL_ERROR;
129
}
130
return CKR_OK;
131
}
132
133
#define INIT_CONTEXT() { CK_RV icret = init_context(); if (icret) return icret; }
134
135
static void
136
snprintf_fill(char *str, size_t size, char fillchar, const char *fmt, ...)
137
{
138
int len;
139
va_list ap;
140
va_start(ap, fmt);
141
len = vsnprintf(str, size, fmt, ap);
142
va_end(ap);
143
if (len < 0 || (size_t)len > size)
144
return;
145
while ((size_t)len < size)
146
str[len++] = fillchar;
147
}
148
149
#ifndef TEST_APP
150
#define printf error_use_st_logf
151
#endif
152
153
#define VERIFY_SESSION_HANDLE(s, state) \
154
{ \
155
CK_RV xret; \
156
xret = verify_session_handle(s, state); \
157
if (xret != CKR_OK) { \
158
/* return CKR_OK */; \
159
} \
160
}
161
162
static CK_RV
163
verify_session_handle(CK_SESSION_HANDLE hSession,
164
struct session_state **state)
165
{
166
size_t i;
167
168
for (i = 0; i < MAX_NUM_SESSION; i++){
169
if (soft_token.state[i].session_handle == hSession)
170
break;
171
}
172
if (i == MAX_NUM_SESSION) {
173
application_error("use of invalid handle: 0x%08lx\n",
174
(unsigned long)hSession);
175
return CKR_SESSION_HANDLE_INVALID;
176
}
177
if (state)
178
*state = &soft_token.state[i];
179
return CKR_OK;
180
}
181
182
static CK_RV
183
object_handle_to_object(CK_OBJECT_HANDLE handle,
184
struct st_object **object)
185
{
186
int i = HANDLE_OBJECT_ID(handle);
187
188
*object = NULL;
189
if (i >= soft_token.object.num_objs)
190
return CKR_ARGUMENTS_BAD;
191
if (soft_token.object.objs[i] == NULL)
192
return CKR_ARGUMENTS_BAD;
193
if (soft_token.object.objs[i]->object_handle != handle)
194
return CKR_ARGUMENTS_BAD;
195
*object = soft_token.object.objs[i];
196
return CKR_OK;
197
}
198
199
static int
200
attributes_match(const struct st_object *obj,
201
const CK_ATTRIBUTE *attributes,
202
CK_ULONG num_attributes)
203
{
204
CK_ULONG i;
205
int j;
206
207
st_logf("attributes_match: %ld\n", (unsigned long)OBJECT_ID(obj));
208
209
for (i = 0; i < num_attributes; i++) {
210
int match = 0;
211
for (j = 0; j < obj->num_attributes; j++) {
212
if (attributes[i].type == obj->attrs[j].attribute.type &&
213
attributes[i].ulValueLen == obj->attrs[j].attribute.ulValueLen &&
214
memcmp(attributes[i].pValue, obj->attrs[j].attribute.pValue,
215
attributes[i].ulValueLen) == 0) {
216
match = 1;
217
break;
218
}
219
}
220
if (match == 0) {
221
st_logf("type %d attribute have no match\n", attributes[i].type);
222
return 0;
223
}
224
}
225
st_logf("attribute matches\n");
226
return 1;
227
}
228
229
static void
230
print_attributes(const CK_ATTRIBUTE *attributes,
231
CK_ULONG num_attributes)
232
{
233
CK_ULONG i;
234
235
st_logf("find objects: attrs: %lu\n", (unsigned long)num_attributes);
236
237
for (i = 0; i < num_attributes; i++) {
238
st_logf(" type: ");
239
switch (attributes[i].type) {
240
case CKA_TOKEN: {
241
CK_BBOOL *ck_true;
242
if (attributes[i].ulValueLen != sizeof(CK_BBOOL)) {
243
application_error("token attribute wrong length\n");
244
break;
245
}
246
ck_true = attributes[i].pValue;
247
st_logf("token: %s", *ck_true ? "TRUE" : "FALSE");
248
break;
249
}
250
case CKA_CLASS: {
251
CK_OBJECT_CLASS *class;
252
if (attributes[i].ulValueLen != sizeof(CK_ULONG)) {
253
application_error("class attribute wrong length\n");
254
break;
255
}
256
class = attributes[i].pValue;
257
st_logf("class ");
258
switch (*class) {
259
case CKO_CERTIFICATE:
260
st_logf("certificate");
261
break;
262
case CKO_PUBLIC_KEY:
263
st_logf("public key");
264
break;
265
case CKO_PRIVATE_KEY:
266
st_logf("private key");
267
break;
268
case CKO_SECRET_KEY:
269
st_logf("secret key");
270
break;
271
case CKO_DOMAIN_PARAMETERS:
272
st_logf("domain parameters");
273
break;
274
default:
275
st_logf("[class %lx]", (long unsigned)*class);
276
break;
277
}
278
break;
279
}
280
case CKA_PRIVATE:
281
st_logf("private");
282
break;
283
case CKA_LABEL:
284
st_logf("label");
285
break;
286
case CKA_APPLICATION:
287
st_logf("application");
288
break;
289
case CKA_VALUE:
290
st_logf("value");
291
break;
292
case CKA_ID:
293
st_logf("id");
294
break;
295
default:
296
st_logf("[unknown 0x%08lx]", (unsigned long)attributes[i].type);
297
break;
298
}
299
st_logf("\n");
300
}
301
}
302
303
static struct st_object *
304
add_st_object(void)
305
{
306
struct st_object *o, **objs;
307
int i;
308
309
o = calloc(1, sizeof(*o));
310
if (o == NULL)
311
return NULL;
312
313
for (i = 0; i < soft_token.object.num_objs; i++) {
314
if (soft_token.object.objs == NULL) {
315
soft_token.object.objs[i] = o;
316
break;
317
}
318
}
319
if (i == soft_token.object.num_objs) {
320
objs = realloc(soft_token.object.objs,
321
(soft_token.object.num_objs + 1) * sizeof(soft_token.object.objs[0]));
322
if (objs == NULL) {
323
free(o);
324
return NULL;
325
}
326
soft_token.object.objs = objs;
327
soft_token.object.objs[soft_token.object.num_objs++] = o;
328
}
329
soft_token.object.objs[i]->object_handle =
330
(random() & (~OBJECT_ID_MASK)) | i;
331
332
return o;
333
}
334
335
static CK_RV
336
add_object_attribute(struct st_object *o,
337
int secret,
338
CK_ATTRIBUTE_TYPE type,
339
CK_VOID_PTR pValue,
340
CK_ULONG ulValueLen)
341
{
342
struct st_attr *a;
343
int i;
344
345
if (pValue == NULL && ulValueLen)
346
return CKR_ARGUMENTS_BAD;
347
348
i = o->num_attributes;
349
a = realloc(o->attrs, (i + 1) * sizeof(o->attrs[0]));
350
if (a == NULL)
351
return CKR_DEVICE_MEMORY;
352
o->attrs = a;
353
o->attrs[i].secret = secret;
354
o->attrs[i].attribute.type = type;
355
o->attrs[i].attribute.pValue = malloc(ulValueLen);
356
if (o->attrs[i].attribute.pValue == NULL && ulValueLen != 0)
357
return CKR_DEVICE_MEMORY;
358
if (ulValueLen)
359
memcpy(o->attrs[i].attribute.pValue, pValue, ulValueLen);
360
o->attrs[i].attribute.ulValueLen = ulValueLen;
361
o->num_attributes++;
362
363
return CKR_OK;
364
}
365
366
static CK_RV
367
add_pubkey_info(hx509_context hxctx, struct st_object *o,
368
CK_KEY_TYPE key_type, hx509_cert cert)
369
{
370
BIGNUM *num;
371
CK_BYTE *modulus = NULL;
372
size_t modulus_len = 0;
373
CK_ULONG modulus_bits = 0;
374
CK_BYTE *exponent = NULL;
375
size_t exponent_len = 0;
376
377
if (key_type != CKK_RSA)
378
return CKR_OK;
379
if (_hx509_cert_private_key(cert) == NULL)
380
return CKR_OK;
381
382
num = _hx509_private_key_get_internal(context,
383
_hx509_cert_private_key(cert),
384
"rsa-modulus");
385
if (num == NULL)
386
return CKR_GENERAL_ERROR;
387
modulus_bits = BN_num_bits(num);
388
389
modulus_len = BN_num_bytes(num);
390
modulus = malloc(modulus_len);
391
BN_bn2bin(num, modulus);
392
BN_free(num);
393
394
add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len);
395
add_object_attribute(o, 0, CKA_MODULUS_BITS,
396
&modulus_bits, sizeof(modulus_bits));
397
398
free(modulus);
399
400
num = _hx509_private_key_get_internal(context,
401
_hx509_cert_private_key(cert),
402
"rsa-exponent");
403
if (num == NULL)
404
return CKR_GENERAL_ERROR;
405
406
exponent_len = BN_num_bytes(num);
407
exponent = malloc(exponent_len);
408
BN_bn2bin(num, exponent);
409
BN_free(num);
410
411
add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT,
412
exponent, exponent_len);
413
414
free(exponent);
415
416
return CKR_OK;
417
}
418
419
420
struct foo {
421
char *label;
422
char *id;
423
};
424
425
static int
426
add_cert(hx509_context hxctx, void *ctx, hx509_cert cert)
427
{
428
static char empty[] = "";
429
struct foo *foo = (struct foo *)ctx;
430
struct st_object *o = NULL;
431
CK_OBJECT_CLASS type;
432
CK_BBOOL bool_true = CK_TRUE;
433
CK_BBOOL bool_false = CK_FALSE;
434
CK_CERTIFICATE_TYPE cert_type = CKC_X_509;
435
CK_KEY_TYPE key_type;
436
CK_MECHANISM_TYPE mech_type;
437
CK_RV ret = CKR_GENERAL_ERROR;
438
int hret;
439
heim_octet_string cert_data, subject_data, issuer_data, serial_data;
440
441
st_logf("adding certificate\n");
442
443
serial_data.data = NULL;
444
serial_data.length = 0;
445
cert_data = subject_data = issuer_data = serial_data;
446
447
hret = hx509_cert_binary(hxctx, cert, &cert_data);
448
if (hret)
449
goto out;
450
451
{
452
hx509_name name;
453
454
hret = hx509_cert_get_issuer(cert, &name);
455
if (hret)
456
goto out;
457
hret = hx509_name_binary(name, &issuer_data);
458
hx509_name_free(&name);
459
if (hret)
460
goto out;
461
462
hret = hx509_cert_get_subject(cert, &name);
463
if (hret)
464
goto out;
465
hret = hx509_name_binary(name, &subject_data);
466
hx509_name_free(&name);
467
if (hret)
468
goto out;
469
}
470
471
{
472
AlgorithmIdentifier alg;
473
474
hret = hx509_cert_get_SPKI_AlgorithmIdentifier(context, cert, &alg);
475
if (hret) {
476
ret = CKR_DEVICE_MEMORY;
477
goto out;
478
}
479
480
key_type = CKK_RSA; /* XXX */
481
482
free_AlgorithmIdentifier(&alg);
483
}
484
485
486
type = CKO_CERTIFICATE;
487
o = add_st_object();
488
if (o == NULL) {
489
ret = CKR_DEVICE_MEMORY;
490
goto out;
491
}
492
493
o->cert = hx509_cert_ref(cert);
494
495
add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
496
add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
497
add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
498
add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
499
add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
500
501
add_object_attribute(o, 0, CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type));
502
add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
503
504
add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
505
add_object_attribute(o, 0, CKA_ISSUER, issuer_data.data, issuer_data.length);
506
add_object_attribute(o, 0, CKA_SERIAL_NUMBER, serial_data.data, serial_data.length);
507
add_object_attribute(o, 0, CKA_VALUE, cert_data.data, cert_data.length);
508
add_object_attribute(o, 0, CKA_TRUSTED, &bool_false, sizeof(bool_false));
509
510
st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o));
511
512
type = CKO_PUBLIC_KEY;
513
o = add_st_object();
514
if (o == NULL) {
515
ret = CKR_DEVICE_MEMORY;
516
goto out;
517
}
518
o->cert = hx509_cert_ref(cert);
519
520
add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
521
add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
522
add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
523
add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
524
add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
525
526
add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
527
add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
528
add_object_attribute(o, 0, CKA_START_DATE, empty, 1); /* XXX */
529
add_object_attribute(o, 0, CKA_END_DATE, empty, 1); /* XXX */
530
add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
531
add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
532
mech_type = CKM_RSA_X_509;
533
add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));
534
535
add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
536
add_object_attribute(o, 0, CKA_ENCRYPT, &bool_true, sizeof(bool_true));
537
add_object_attribute(o, 0, CKA_VERIFY, &bool_true, sizeof(bool_true));
538
add_object_attribute(o, 0, CKA_VERIFY_RECOVER, &bool_false, sizeof(bool_false));
539
add_object_attribute(o, 0, CKA_WRAP, &bool_true, sizeof(bool_true));
540
add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true));
541
542
add_pubkey_info(hxctx, o, key_type, cert);
543
544
st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o));
545
546
if (hx509_cert_have_private_key(cert)) {
547
CK_FLAGS flags;
548
549
type = CKO_PRIVATE_KEY;
550
o = add_st_object();
551
if (o == NULL) {
552
ret = CKR_DEVICE_MEMORY;
553
goto out;
554
}
555
o->cert = hx509_cert_ref(cert);
556
557
add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
558
add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
559
add_object_attribute(o, 0, CKA_PRIVATE, &bool_true, sizeof(bool_false));
560
add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
561
add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
562
563
add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
564
add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
565
add_object_attribute(o, 0, CKA_START_DATE, empty, 1); /* XXX */
566
add_object_attribute(o, 0, CKA_END_DATE, empty, 1); /* XXX */
567
add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
568
add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
569
mech_type = CKM_RSA_X_509;
570
add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));
571
572
add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
573
add_object_attribute(o, 0, CKA_SENSITIVE, &bool_true, sizeof(bool_true));
574
add_object_attribute(o, 0, CKA_SECONDARY_AUTH, &bool_false, sizeof(bool_true));
575
flags = 0;
576
add_object_attribute(o, 0, CKA_AUTH_PIN_FLAGS, &flags, sizeof(flags));
577
578
add_object_attribute(o, 0, CKA_DECRYPT, &bool_true, sizeof(bool_true));
579
add_object_attribute(o, 0, CKA_SIGN, &bool_true, sizeof(bool_true));
580
add_object_attribute(o, 0, CKA_SIGN_RECOVER, &bool_false, sizeof(bool_false));
581
add_object_attribute(o, 0, CKA_UNWRAP, &bool_true, sizeof(bool_true));
582
add_object_attribute(o, 0, CKA_EXTRACTABLE, &bool_true, sizeof(bool_true));
583
add_object_attribute(o, 0, CKA_NEVER_EXTRACTABLE, &bool_false, sizeof(bool_false));
584
585
add_pubkey_info(hxctx, o, key_type, cert);
586
}
587
588
ret = CKR_OK;
589
out:
590
if (ret != CKR_OK) {
591
st_logf("something went wrong when adding cert!\n");
592
593
/* XXX wack o */;
594
}
595
hx509_xfree(cert_data.data);
596
hx509_xfree(serial_data.data);
597
hx509_xfree(issuer_data.data);
598
hx509_xfree(subject_data.data);
599
600
return 0;
601
}
602
603
static CK_RV
604
add_certificate(const char *cert_file,
605
const char *pin,
606
char *id,
607
char *label)
608
{
609
hx509_certs certs;
610
hx509_lock lock = NULL;
611
int ret, flags = 0;
612
613
struct foo foo;
614
foo.id = id;
615
foo.label = label;
616
617
if (pin == NULL)
618
flags |= HX509_CERTS_UNPROTECT_ALL;
619
620
if (pin) {
621
char *str;
622
asprintf(&str, "PASS:%s", pin);
623
624
hx509_lock_init(context, &lock);
625
hx509_lock_command_string(lock, str);
626
627
memset(str, 0, strlen(str));
628
free(str);
629
}
630
631
ret = hx509_certs_init(context, cert_file, flags, lock, &certs);
632
if (ret) {
633
st_logf("failed to open file %s\n", cert_file);
634
return CKR_GENERAL_ERROR;
635
}
636
637
ret = hx509_certs_iter_f(context, certs, add_cert, &foo);
638
hx509_certs_free(&certs);
639
if (ret) {
640
st_logf("failed adding certs from file %s\n", cert_file);
641
return CKR_GENERAL_ERROR;
642
}
643
644
return CKR_OK;
645
}
646
647
static void
648
find_object_final(struct session_state *state)
649
{
650
if (state->find.attributes) {
651
CK_ULONG i;
652
653
for (i = 0; i < state->find.num_attributes; i++) {
654
if (state->find.attributes[i].pValue)
655
free(state->find.attributes[i].pValue);
656
}
657
free(state->find.attributes);
658
state->find.attributes = NULL;
659
state->find.num_attributes = 0;
660
state->find.next_object = -1;
661
}
662
}
663
664
static void
665
reset_crypto_state(struct session_state *state)
666
{
667
state->sign_object = -1;
668
if (state->sign_mechanism)
669
free(state->sign_mechanism);
670
state->sign_mechanism = NULL_PTR;
671
state->verify_object = -1;
672
if (state->verify_mechanism)
673
free(state->verify_mechanism);
674
state->verify_mechanism = NULL_PTR;
675
}
676
677
static void
678
close_session(struct session_state *state)
679
{
680
if (state->find.attributes) {
681
application_error("application didn't do C_FindObjectsFinal\n");
682
find_object_final(state);
683
}
684
685
state->session_handle = CK_INVALID_HANDLE;
686
soft_token.application = NULL_PTR;
687
soft_token.notify = NULL_PTR;
688
reset_crypto_state(state);
689
}
690
691
static const char *
692
has_session(void)
693
{
694
return soft_token.open_sessions > 0 ? "yes" : "no";
695
}
696
697
static CK_RV
698
read_conf_file(const char *fn, CK_USER_TYPE userType, const char *pin)
699
{
700
char buf[1024], *type, *s, *p;
701
FILE *f;
702
CK_RV ret = CKR_OK;
703
CK_RV failed = CKR_OK;
704
705
if (fn == NULL) {
706
st_logf("Can't open configuration file. No file specified\n");
707
return CKR_GENERAL_ERROR;
708
}
709
710
f = fopen(fn, "r");
711
if (f == NULL) {
712
st_logf("can't open configuration file %s\n", fn);
713
return CKR_GENERAL_ERROR;
714
}
715
rk_cloexec_file(f);
716
717
while(fgets(buf, sizeof(buf), f) != NULL) {
718
buf[strcspn(buf, "\n")] = '\0';
719
720
st_logf("line: %s\n", buf);
721
722
p = buf;
723
while (isspace((unsigned char)*p))
724
p++;
725
if (*p == '#')
726
continue;
727
while (isspace((unsigned char)*p))
728
p++;
729
730
s = NULL;
731
type = strtok_r(p, "\t", &s);
732
if (type == NULL)
733
continue;
734
735
if (strcasecmp("certificate", type) == 0) {
736
char *cert, *id, *label;
737
738
id = strtok_r(NULL, "\t", &s);
739
if (id == NULL) {
740
st_logf("no id\n");
741
continue;
742
}
743
st_logf("id: %s\n", id);
744
label = strtok_r(NULL, "\t", &s);
745
if (label == NULL) {
746
st_logf("no label\n");
747
continue;
748
}
749
cert = strtok_r(NULL, "\t", &s);
750
if (cert == NULL) {
751
st_logf("no certfiicate store\n");
752
continue;
753
}
754
755
st_logf("adding: %s: %s in file %s\n", id, label, cert);
756
757
ret = add_certificate(cert, pin, id, label);
758
if (ret)
759
failed = ret;
760
} else if (strcasecmp("debug", type) == 0) {
761
char *name;
762
763
name = strtok_r(NULL, "\t", &s);
764
if (name == NULL) {
765
st_logf("no filename\n");
766
continue;
767
}
768
769
if (soft_token.logfile)
770
fclose(soft_token.logfile);
771
772
if (strcasecmp(name, "stdout") == 0)
773
soft_token.logfile = stdout;
774
else {
775
soft_token.logfile = fopen(name, "a");
776
if (soft_token.logfile)
777
rk_cloexec_file(soft_token.logfile);
778
}
779
if (soft_token.logfile == NULL)
780
st_logf("failed to open file: %s\n", name);
781
782
} else if (strcasecmp("app-fatal", type) == 0) {
783
char *name;
784
785
name = strtok_r(NULL, "\t", &s);
786
if (name == NULL) {
787
st_logf("argument to app-fatal\n");
788
continue;
789
}
790
791
if (strcmp(name, "true") == 0 || strcmp(name, "on") == 0)
792
soft_token.flags.app_error_fatal = 1;
793
else if (strcmp(name, "false") == 0 || strcmp(name, "off") == 0)
794
soft_token.flags.app_error_fatal = 0;
795
else
796
st_logf("unknown app-fatal: %s\n", name);
797
798
} else {
799
st_logf("unknown type: %s\n", type);
800
}
801
}
802
803
fclose(f);
804
805
return failed;
806
}
807
808
static CK_RV
809
func_not_supported(void)
810
{
811
st_logf("function not supported\n");
812
return CKR_FUNCTION_NOT_SUPPORTED;
813
}
814
815
static char *
816
get_config_file_for_user(void)
817
{
818
char *fn = NULL;
819
820
#ifndef _WIN32
821
char *home = NULL;
822
823
if (!issuid()) {
824
fn = getenv("SOFTPKCS11RC");
825
if (fn)
826
fn = strdup(fn);
827
home = getenv("HOME");
828
}
829
if (fn == NULL && home == NULL) {
830
struct passwd *pw = getpwuid(getuid());
831
if(pw != NULL)
832
home = pw->pw_dir;
833
}
834
if (fn == NULL) {
835
if (home)
836
asprintf(&fn, "%s/.soft-token.rc", home);
837
else
838
fn = strdup("/etc/soft-token.rc");
839
}
840
#else /* Windows */
841
842
char appdatafolder[MAX_PATH];
843
844
fn = getenv("SOFTPKCS11RC");
845
846
/* Retrieve the roaming AppData folder for the current user. The
847
current user is the user account represented by the current
848
thread token. */
849
850
if (fn == NULL &&
851
SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, appdatafolder))) {
852
853
asprintf(&fn, "%s\\.soft-token.rc", appdatafolder);
854
}
855
856
#endif /* _WIN32 */
857
858
return fn;
859
}
860
861
862
CK_RV CK_SPEC
863
C_Initialize(CK_VOID_PTR a)
864
{
865
CK_C_INITIALIZE_ARGS_PTR args = a;
866
CK_RV ret;
867
size_t i;
868
869
st_logf("Initialize\n");
870
871
INIT_CONTEXT();
872
873
OpenSSL_add_all_algorithms();
874
875
srandom(getpid() ^ (int) time(NULL));
876
877
for (i = 0; i < MAX_NUM_SESSION; i++) {
878
soft_token.state[i].session_handle = CK_INVALID_HANDLE;
879
soft_token.state[i].find.attributes = NULL;
880
soft_token.state[i].find.num_attributes = 0;
881
soft_token.state[i].find.next_object = -1;
882
reset_crypto_state(&soft_token.state[i]);
883
}
884
885
soft_token.flags.hardware_slot = 1;
886
soft_token.flags.app_error_fatal = 0;
887
soft_token.flags.login_done = 0;
888
889
soft_token.object.objs = NULL;
890
soft_token.object.num_objs = 0;
891
892
soft_token.logfile = NULL;
893
#if 0
894
soft_token.logfile = stdout;
895
#endif
896
#if 0
897
soft_token.logfile = fopen("/tmp/log-pkcs11.txt", "a");
898
#endif
899
900
if (a != NULL_PTR) {
901
st_logf("\tCreateMutex:\t%p\n", args->CreateMutex);
902
st_logf("\tDestroyMutext\t%p\n", args->DestroyMutex);
903
st_logf("\tLockMutext\t%p\n", args->LockMutex);
904
st_logf("\tUnlockMutext\t%p\n", args->UnlockMutex);
905
st_logf("\tFlags\t%04x\n", (unsigned int)args->flags);
906
}
907
908
soft_token.config_file = get_config_file_for_user();
909
910
/*
911
* This operations doesn't return CKR_OK if any of the
912
* certificates failes to be unparsed (ie password protected).
913
*/
914
ret = read_conf_file(soft_token.config_file, CKU_USER, NULL);
915
if (ret == CKR_OK)
916
soft_token.flags.login_done = 1;
917
918
return CKR_OK;
919
}
920
921
CK_RV
922
C_Finalize(CK_VOID_PTR args)
923
{
924
size_t i;
925
926
INIT_CONTEXT();
927
928
st_logf("Finalize\n");
929
930
for (i = 0; i < MAX_NUM_SESSION; i++) {
931
if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) {
932
application_error("application finalized without "
933
"closing session\n");
934
close_session(&soft_token.state[i]);
935
}
936
}
937
938
return CKR_OK;
939
}
940
941
CK_RV
942
C_GetInfo(CK_INFO_PTR args)
943
{
944
INIT_CONTEXT();
945
946
st_logf("GetInfo\n");
947
948
memset(args, 17, sizeof(*args));
949
args->cryptokiVersion.major = 2;
950
args->cryptokiVersion.minor = 10;
951
snprintf_fill((char *)args->manufacturerID,
952
sizeof(args->manufacturerID),
953
' ',
954
"Heimdal hx509 SoftToken");
955
snprintf_fill((char *)args->libraryDescription,
956
sizeof(args->libraryDescription), ' ',
957
"Heimdal hx509 SoftToken");
958
args->libraryVersion.major = 2;
959
args->libraryVersion.minor = 0;
960
961
return CKR_OK;
962
}
963
964
extern CK_FUNCTION_LIST funcs;
965
966
CK_RV
967
C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
968
{
969
INIT_CONTEXT();
970
971
*ppFunctionList = &funcs;
972
return CKR_OK;
973
}
974
975
CK_RV
976
C_GetSlotList(CK_BBOOL tokenPresent,
977
CK_SLOT_ID_PTR pSlotList,
978
CK_ULONG_PTR pulCount)
979
{
980
INIT_CONTEXT();
981
st_logf("GetSlotList: %s\n",
982
tokenPresent ? "tokenPresent" : "token not Present");
983
if (pSlotList)
984
pSlotList[0] = 1;
985
*pulCount = 1;
986
return CKR_OK;
987
}
988
989
CK_RV
990
C_GetSlotInfo(CK_SLOT_ID slotID,
991
CK_SLOT_INFO_PTR pInfo)
992
{
993
INIT_CONTEXT();
994
st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID, has_session());
995
996
memset(pInfo, 18, sizeof(*pInfo));
997
998
if (slotID != 1)
999
return CKR_ARGUMENTS_BAD;
1000
1001
snprintf_fill((char *)pInfo->slotDescription,
1002
sizeof(pInfo->slotDescription),
1003
' ',
1004
"Heimdal hx509 SoftToken (slot)");
1005
snprintf_fill((char *)pInfo->manufacturerID,
1006
sizeof(pInfo->manufacturerID),
1007
' ',
1008
"Heimdal hx509 SoftToken (slot)");
1009
pInfo->flags = CKF_TOKEN_PRESENT;
1010
if (soft_token.flags.hardware_slot)
1011
pInfo->flags |= CKF_HW_SLOT;
1012
pInfo->hardwareVersion.major = 1;
1013
pInfo->hardwareVersion.minor = 0;
1014
pInfo->firmwareVersion.major = 1;
1015
pInfo->firmwareVersion.minor = 0;
1016
1017
return CKR_OK;
1018
}
1019
1020
CK_RV
1021
C_GetTokenInfo(CK_SLOT_ID slotID,
1022
CK_TOKEN_INFO_PTR pInfo)
1023
{
1024
INIT_CONTEXT();
1025
st_logf("GetTokenInfo: %s\n", has_session());
1026
1027
memset(pInfo, 19, sizeof(*pInfo));
1028
1029
snprintf_fill((char *)pInfo->label,
1030
sizeof(pInfo->label),
1031
' ',
1032
"Heimdal hx509 SoftToken (token)");
1033
snprintf_fill((char *)pInfo->manufacturerID,
1034
sizeof(pInfo->manufacturerID),
1035
' ',
1036
"Heimdal hx509 SoftToken (token)");
1037
snprintf_fill((char *)pInfo->model,
1038
sizeof(pInfo->model),
1039
' ',
1040
"Heimdal hx509 SoftToken (token)");
1041
snprintf_fill((char *)pInfo->serialNumber,
1042
sizeof(pInfo->serialNumber),
1043
' ',
1044
"4711");
1045
pInfo->flags =
1046
CKF_TOKEN_INITIALIZED |
1047
CKF_USER_PIN_INITIALIZED;
1048
1049
if (soft_token.flags.login_done == 0)
1050
pInfo->flags |= CKF_LOGIN_REQUIRED;
1051
1052
/* CFK_RNG |
1053
CKF_RESTORE_KEY_NOT_NEEDED |
1054
*/
1055
pInfo->ulMaxSessionCount = MAX_NUM_SESSION;
1056
pInfo->ulSessionCount = soft_token.open_sessions;
1057
pInfo->ulMaxRwSessionCount = MAX_NUM_SESSION;
1058
pInfo->ulRwSessionCount = soft_token.open_sessions;
1059
pInfo->ulMaxPinLen = 1024;
1060
pInfo->ulMinPinLen = 0;
1061
pInfo->ulTotalPublicMemory = 4711;
1062
pInfo->ulFreePublicMemory = 4712;
1063
pInfo->ulTotalPrivateMemory = 4713;
1064
pInfo->ulFreePrivateMemory = 4714;
1065
pInfo->hardwareVersion.major = 2;
1066
pInfo->hardwareVersion.minor = 0;
1067
pInfo->firmwareVersion.major = 2;
1068
pInfo->firmwareVersion.minor = 0;
1069
1070
return CKR_OK;
1071
}
1072
1073
CK_RV
1074
C_GetMechanismList(CK_SLOT_ID slotID,
1075
CK_MECHANISM_TYPE_PTR pMechanismList,
1076
CK_ULONG_PTR pulCount)
1077
{
1078
INIT_CONTEXT();
1079
st_logf("GetMechanismList\n");
1080
1081
*pulCount = 1;
1082
if (pMechanismList == NULL_PTR)
1083
return CKR_OK;
1084
pMechanismList[1] = CKM_RSA_PKCS;
1085
1086
return CKR_OK;
1087
}
1088
1089
CK_RV
1090
C_GetMechanismInfo(CK_SLOT_ID slotID,
1091
CK_MECHANISM_TYPE type,
1092
CK_MECHANISM_INFO_PTR pInfo)
1093
{
1094
INIT_CONTEXT();
1095
st_logf("GetMechanismInfo: slot %d type: %d\n",
1096
(int)slotID, (int)type);
1097
memset(pInfo, 0, sizeof(*pInfo));
1098
1099
return CKR_OK;
1100
}
1101
1102
CK_RV
1103
C_InitToken(CK_SLOT_ID slotID,
1104
CK_UTF8CHAR_PTR pPin,
1105
CK_ULONG ulPinLen,
1106
CK_UTF8CHAR_PTR pLabel)
1107
{
1108
INIT_CONTEXT();
1109
st_logf("InitToken: slot %d\n", (int)slotID);
1110
return CKR_FUNCTION_NOT_SUPPORTED;
1111
}
1112
1113
CK_RV
1114
C_OpenSession(CK_SLOT_ID slotID,
1115
CK_FLAGS flags,
1116
CK_VOID_PTR pApplication,
1117
CK_NOTIFY Notify,
1118
CK_SESSION_HANDLE_PTR phSession)
1119
{
1120
size_t i;
1121
INIT_CONTEXT();
1122
st_logf("OpenSession: slot: %d\n", (int)slotID);
1123
1124
if (soft_token.open_sessions == MAX_NUM_SESSION)
1125
return CKR_SESSION_COUNT;
1126
1127
soft_token.application = pApplication;
1128
soft_token.notify = Notify;
1129
1130
for (i = 0; i < MAX_NUM_SESSION; i++)
1131
if (soft_token.state[i].session_handle == CK_INVALID_HANDLE)
1132
break;
1133
if (i == MAX_NUM_SESSION)
1134
abort();
1135
1136
soft_token.open_sessions++;
1137
1138
soft_token.state[i].session_handle =
1139
(CK_SESSION_HANDLE)(random() & 0xfffff);
1140
*phSession = soft_token.state[i].session_handle;
1141
1142
return CKR_OK;
1143
}
1144
1145
CK_RV
1146
C_CloseSession(CK_SESSION_HANDLE hSession)
1147
{
1148
struct session_state *state;
1149
INIT_CONTEXT();
1150
st_logf("CloseSession\n");
1151
1152
if (verify_session_handle(hSession, &state) != CKR_OK)
1153
application_error("closed session not open");
1154
else
1155
close_session(state);
1156
1157
return CKR_OK;
1158
}
1159
1160
CK_RV
1161
C_CloseAllSessions(CK_SLOT_ID slotID)
1162
{
1163
size_t i;
1164
INIT_CONTEXT();
1165
1166
st_logf("CloseAllSessions\n");
1167
1168
for (i = 0; i < MAX_NUM_SESSION; i++)
1169
if (soft_token.state[i].session_handle != CK_INVALID_HANDLE)
1170
close_session(&soft_token.state[i]);
1171
1172
return CKR_OK;
1173
}
1174
1175
CK_RV
1176
C_GetSessionInfo(CK_SESSION_HANDLE hSession,
1177
CK_SESSION_INFO_PTR pInfo)
1178
{
1179
st_logf("GetSessionInfo\n");
1180
INIT_CONTEXT();
1181
1182
VERIFY_SESSION_HANDLE(hSession, NULL);
1183
1184
memset(pInfo, 20, sizeof(*pInfo));
1185
1186
pInfo->slotID = 1;
1187
if (soft_token.flags.login_done)
1188
pInfo->state = CKS_RO_USER_FUNCTIONS;
1189
else
1190
pInfo->state = CKS_RO_PUBLIC_SESSION;
1191
pInfo->flags = CKF_SERIAL_SESSION;
1192
pInfo->ulDeviceError = 0;
1193
1194
return CKR_OK;
1195
}
1196
1197
CK_RV
1198
C_Login(CK_SESSION_HANDLE hSession,
1199
CK_USER_TYPE userType,
1200
CK_UTF8CHAR_PTR pPin,
1201
CK_ULONG ulPinLen)
1202
{
1203
char *pin = NULL;
1204
CK_RV ret;
1205
INIT_CONTEXT();
1206
1207
st_logf("Login\n");
1208
1209
VERIFY_SESSION_HANDLE(hSession, NULL);
1210
1211
if (pPin != NULL_PTR) {
1212
asprintf(&pin, "%.*s", (int)ulPinLen, pPin);
1213
st_logf("type: %d password: %s\n", (int)userType, pin);
1214
}
1215
1216
/*
1217
* Login
1218
*/
1219
1220
ret = read_conf_file(soft_token.config_file, userType, pin);
1221
if (ret == CKR_OK)
1222
soft_token.flags.login_done = 1;
1223
1224
free(pin);
1225
1226
return soft_token.flags.login_done ? CKR_OK : CKR_PIN_INCORRECT;
1227
}
1228
1229
CK_RV
1230
C_Logout(CK_SESSION_HANDLE hSession)
1231
{
1232
st_logf("Logout\n");
1233
INIT_CONTEXT();
1234
1235
VERIFY_SESSION_HANDLE(hSession, NULL);
1236
return CKR_FUNCTION_NOT_SUPPORTED;
1237
}
1238
1239
CK_RV
1240
C_GetObjectSize(CK_SESSION_HANDLE hSession,
1241
CK_OBJECT_HANDLE hObject,
1242
CK_ULONG_PTR pulSize)
1243
{
1244
st_logf("GetObjectSize\n");
1245
INIT_CONTEXT();
1246
1247
VERIFY_SESSION_HANDLE(hSession, NULL);
1248
return CKR_FUNCTION_NOT_SUPPORTED;
1249
}
1250
1251
CK_RV
1252
C_GetAttributeValue(CK_SESSION_HANDLE hSession,
1253
CK_OBJECT_HANDLE hObject,
1254
CK_ATTRIBUTE_PTR pTemplate,
1255
CK_ULONG ulCount)
1256
{
1257
struct session_state *state;
1258
struct st_object *obj;
1259
CK_ULONG i;
1260
CK_RV ret;
1261
int j;
1262
1263
INIT_CONTEXT();
1264
1265
st_logf("GetAttributeValue: %lx\n",
1266
(unsigned long)HANDLE_OBJECT_ID(hObject));
1267
VERIFY_SESSION_HANDLE(hSession, &state);
1268
1269
if ((ret = object_handle_to_object(hObject, &obj)) != CKR_OK) {
1270
st_logf("object not found: %lx\n",
1271
(unsigned long)HANDLE_OBJECT_ID(hObject));
1272
return ret;
1273
}
1274
1275
for (i = 0; i < ulCount; i++) {
1276
st_logf(" getting 0x%08lx\n", (unsigned long)pTemplate[i].type);
1277
for (j = 0; j < obj->num_attributes; j++) {
1278
if (obj->attrs[j].secret) {
1279
pTemplate[i].ulValueLen = (CK_ULONG)-1;
1280
break;
1281
}
1282
if (pTemplate[i].type == obj->attrs[j].attribute.type) {
1283
if (pTemplate[i].pValue != NULL_PTR && obj->attrs[j].secret == 0) {
1284
if (pTemplate[i].ulValueLen >= obj->attrs[j].attribute.ulValueLen)
1285
memcpy(pTemplate[i].pValue, obj->attrs[j].attribute.pValue,
1286
obj->attrs[j].attribute.ulValueLen);
1287
}
1288
pTemplate[i].ulValueLen = obj->attrs[j].attribute.ulValueLen;
1289
break;
1290
}
1291
}
1292
if (j == obj->num_attributes) {
1293
st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate[i].type);
1294
pTemplate[i].ulValueLen = (CK_ULONG)-1;
1295
}
1296
1297
}
1298
return CKR_OK;
1299
}
1300
1301
CK_RV
1302
C_FindObjectsInit(CK_SESSION_HANDLE hSession,
1303
CK_ATTRIBUTE_PTR pTemplate,
1304
CK_ULONG ulCount)
1305
{
1306
struct session_state *state;
1307
1308
st_logf("FindObjectsInit\n");
1309
1310
INIT_CONTEXT();
1311
1312
VERIFY_SESSION_HANDLE(hSession, &state);
1313
1314
if (state->find.next_object != -1) {
1315
application_error("application didn't do C_FindObjectsFinal\n");
1316
find_object_final(state);
1317
}
1318
if (ulCount) {
1319
CK_ULONG i;
1320
1321
print_attributes(pTemplate, ulCount);
1322
1323
state->find.attributes =
1324
calloc(1, ulCount * sizeof(state->find.attributes[0]));
1325
if (state->find.attributes == NULL)
1326
return CKR_DEVICE_MEMORY;
1327
for (i = 0; i < ulCount; i++) {
1328
state->find.attributes[i].pValue =
1329
malloc(pTemplate[i].ulValueLen);
1330
if (state->find.attributes[i].pValue == NULL) {
1331
find_object_final(state);
1332
return CKR_DEVICE_MEMORY;
1333
}
1334
memcpy(state->find.attributes[i].pValue,
1335
pTemplate[i].pValue, pTemplate[i].ulValueLen);
1336
state->find.attributes[i].type = pTemplate[i].type;
1337
state->find.attributes[i].ulValueLen = pTemplate[i].ulValueLen;
1338
}
1339
state->find.num_attributes = ulCount;
1340
state->find.next_object = 0;
1341
} else {
1342
st_logf("find all objects\n");
1343
state->find.attributes = NULL;
1344
state->find.num_attributes = 0;
1345
state->find.next_object = 0;
1346
}
1347
1348
return CKR_OK;
1349
}
1350
1351
CK_RV
1352
C_FindObjects(CK_SESSION_HANDLE hSession,
1353
CK_OBJECT_HANDLE_PTR phObject,
1354
CK_ULONG ulMaxObjectCount,
1355
CK_ULONG_PTR pulObjectCount)
1356
{
1357
struct session_state *state;
1358
int i;
1359
1360
INIT_CONTEXT();
1361
1362
st_logf("FindObjects\n");
1363
1364
VERIFY_SESSION_HANDLE(hSession, &state);
1365
1366
if (state->find.next_object == -1) {
1367
application_error("application didn't do C_FindObjectsInit\n");
1368
return CKR_ARGUMENTS_BAD;
1369
}
1370
if (ulMaxObjectCount == 0) {
1371
application_error("application asked for 0 objects\n");
1372
return CKR_ARGUMENTS_BAD;
1373
}
1374
*pulObjectCount = 0;
1375
for (i = state->find.next_object; i < soft_token.object.num_objs; i++) {
1376
st_logf("FindObjects: %d\n", i);
1377
state->find.next_object = i + 1;
1378
if (attributes_match(soft_token.object.objs[i],
1379
state->find.attributes,
1380
state->find.num_attributes)) {
1381
*phObject++ = soft_token.object.objs[i]->object_handle;
1382
ulMaxObjectCount--;
1383
(*pulObjectCount)++;
1384
if (ulMaxObjectCount == 0)
1385
break;
1386
}
1387
}
1388
return CKR_OK;
1389
}
1390
1391
CK_RV
1392
C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
1393
{
1394
struct session_state *state;
1395
1396
INIT_CONTEXT();
1397
1398
st_logf("FindObjectsFinal\n");
1399
VERIFY_SESSION_HANDLE(hSession, &state);
1400
find_object_final(state);
1401
return CKR_OK;
1402
}
1403
1404
static CK_RV
1405
commonInit(CK_ATTRIBUTE *attr_match, int attr_match_len,
1406
const CK_MECHANISM_TYPE *mechs, int mechs_len,
1407
const CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey,
1408
struct st_object **o)
1409
{
1410
CK_RV ret;
1411
int i;
1412
1413
*o = NULL;
1414
if ((ret = object_handle_to_object(hKey, o)) != CKR_OK)
1415
return ret;
1416
1417
ret = attributes_match(*o, attr_match, attr_match_len);
1418
if (!ret) {
1419
application_error("called commonInit on key that doesn't "
1420
"support required attr");
1421
return CKR_ARGUMENTS_BAD;
1422
}
1423
1424
for (i = 0; i < mechs_len; i++)
1425
if (mechs[i] == pMechanism->mechanism)
1426
break;
1427
if (i == mechs_len) {
1428
application_error("called mech (%08lx) not supported\n",
1429
pMechanism->mechanism);
1430
return CKR_ARGUMENTS_BAD;
1431
}
1432
return CKR_OK;
1433
}
1434
1435
1436
static CK_RV
1437
dup_mechanism(CK_MECHANISM_PTR *dp, const CK_MECHANISM_PTR pMechanism)
1438
{
1439
CK_MECHANISM_PTR p;
1440
1441
p = malloc(sizeof(*p));
1442
if (p == NULL)
1443
return CKR_DEVICE_MEMORY;
1444
1445
if (*dp)
1446
free(*dp);
1447
*dp = p;
1448
memcpy(p, pMechanism, sizeof(*p));
1449
1450
return CKR_OK;
1451
}
1452
1453
CK_RV
1454
C_DigestInit(CK_SESSION_HANDLE hSession,
1455
CK_MECHANISM_PTR pMechanism)
1456
{
1457
st_logf("DigestInit\n");
1458
INIT_CONTEXT();
1459
VERIFY_SESSION_HANDLE(hSession, NULL);
1460
return CKR_FUNCTION_NOT_SUPPORTED;
1461
}
1462
1463
CK_RV
1464
C_SignInit(CK_SESSION_HANDLE hSession,
1465
CK_MECHANISM_PTR pMechanism,
1466
CK_OBJECT_HANDLE hKey)
1467
{
1468
struct session_state *state;
1469
CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS };
1470
CK_BBOOL bool_true = CK_TRUE;
1471
CK_ATTRIBUTE attr[] = {
1472
{ CKA_SIGN, &bool_true, sizeof(bool_true) }
1473
};
1474
struct st_object *o;
1475
CK_RV ret;
1476
1477
INIT_CONTEXT();
1478
st_logf("SignInit\n");
1479
VERIFY_SESSION_HANDLE(hSession, &state);
1480
1481
ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
1482
mechs, sizeof(mechs)/sizeof(mechs[0]),
1483
pMechanism, hKey, &o);
1484
if (ret)
1485
return ret;
1486
1487
ret = dup_mechanism(&state->sign_mechanism, pMechanism);
1488
if (ret == CKR_OK)
1489
state->sign_object = OBJECT_ID(o);
1490
1491
return CKR_OK;
1492
}
1493
1494
CK_RV
1495
C_Sign(CK_SESSION_HANDLE hSession,
1496
CK_BYTE_PTR pData,
1497
CK_ULONG ulDataLen,
1498
CK_BYTE_PTR pSignature,
1499
CK_ULONG_PTR pulSignatureLen)
1500
{
1501
struct session_state *state;
1502
struct st_object *o;
1503
CK_RV ret;
1504
int hret;
1505
const AlgorithmIdentifier *alg;
1506
heim_octet_string sig, data;
1507
1508
INIT_CONTEXT();
1509
st_logf("Sign\n");
1510
VERIFY_SESSION_HANDLE(hSession, &state);
1511
1512
sig.data = NULL;
1513
sig.length = 0;
1514
1515
if (state->sign_object == -1)
1516
return CKR_ARGUMENTS_BAD;
1517
1518
if (pulSignatureLen == NULL) {
1519
st_logf("signature len NULL\n");
1520
ret = CKR_ARGUMENTS_BAD;
1521
goto out;
1522
}
1523
1524
if (pData == NULL_PTR) {
1525
st_logf("data NULL\n");
1526
ret = CKR_ARGUMENTS_BAD;
1527
goto out;
1528
}
1529
1530
o = soft_token.object.objs[state->sign_object];
1531
1532
if (hx509_cert_have_private_key(o->cert) == 0) {
1533
st_logf("private key NULL\n");
1534
return CKR_ARGUMENTS_BAD;
1535
}
1536
1537
switch(state->sign_mechanism->mechanism) {
1538
case CKM_RSA_PKCS:
1539
alg = hx509_signature_rsa_pkcs1_x509();
1540
break;
1541
default:
1542
ret = CKR_FUNCTION_NOT_SUPPORTED;
1543
goto out;
1544
}
1545
1546
data.data = pData;
1547
data.length = ulDataLen;
1548
1549
hret = _hx509_create_signature(context,
1550
_hx509_cert_private_key(o->cert),
1551
alg,
1552
&data,
1553
NULL,
1554
&sig);
1555
if (hret) {
1556
ret = CKR_DEVICE_ERROR;
1557
goto out;
1558
}
1559
*pulSignatureLen = sig.length;
1560
1561
if (pSignature != NULL_PTR)
1562
memcpy(pSignature, sig.data, sig.length);
1563
1564
ret = CKR_OK;
1565
out:
1566
if (sig.data) {
1567
memset(sig.data, 0, sig.length);
1568
der_free_octet_string(&sig);
1569
}
1570
return ret;
1571
}
1572
1573
CK_RV
1574
C_SignUpdate(CK_SESSION_HANDLE hSession,
1575
CK_BYTE_PTR pPart,
1576
CK_ULONG ulPartLen)
1577
{
1578
INIT_CONTEXT();
1579
st_logf("SignUpdate\n");
1580
VERIFY_SESSION_HANDLE(hSession, NULL);
1581
return CKR_FUNCTION_NOT_SUPPORTED;
1582
}
1583
1584
1585
CK_RV
1586
C_SignFinal(CK_SESSION_HANDLE hSession,
1587
CK_BYTE_PTR pSignature,
1588
CK_ULONG_PTR pulSignatureLen)
1589
{
1590
INIT_CONTEXT();
1591
st_logf("SignUpdate\n");
1592
VERIFY_SESSION_HANDLE(hSession, NULL);
1593
return CKR_FUNCTION_NOT_SUPPORTED;
1594
}
1595
1596
CK_RV
1597
C_VerifyInit(CK_SESSION_HANDLE hSession,
1598
CK_MECHANISM_PTR pMechanism,
1599
CK_OBJECT_HANDLE hKey)
1600
{
1601
struct session_state *state;
1602
CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS };
1603
CK_BBOOL bool_true = CK_TRUE;
1604
CK_ATTRIBUTE attr[] = {
1605
{ CKA_VERIFY, &bool_true, sizeof(bool_true) }
1606
};
1607
struct st_object *o;
1608
CK_RV ret;
1609
1610
INIT_CONTEXT();
1611
st_logf("VerifyInit\n");
1612
VERIFY_SESSION_HANDLE(hSession, &state);
1613
1614
ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
1615
mechs, sizeof(mechs)/sizeof(mechs[0]),
1616
pMechanism, hKey, &o);
1617
if (ret)
1618
return ret;
1619
1620
ret = dup_mechanism(&state->verify_mechanism, pMechanism);
1621
if (ret == CKR_OK)
1622
state->verify_object = OBJECT_ID(o);
1623
1624
return ret;
1625
}
1626
1627
CK_RV
1628
C_Verify(CK_SESSION_HANDLE hSession,
1629
CK_BYTE_PTR pData,
1630
CK_ULONG ulDataLen,
1631
CK_BYTE_PTR pSignature,
1632
CK_ULONG ulSignatureLen)
1633
{
1634
struct session_state *state;
1635
struct st_object *o;
1636
const AlgorithmIdentifier *alg;
1637
CK_RV ret;
1638
int hret;
1639
heim_octet_string data, sig;
1640
1641
INIT_CONTEXT();
1642
st_logf("Verify\n");
1643
VERIFY_SESSION_HANDLE(hSession, &state);
1644
1645
if (state->verify_object == -1)
1646
return CKR_ARGUMENTS_BAD;
1647
1648
o = soft_token.object.objs[state->verify_object];
1649
1650
switch(state->verify_mechanism->mechanism) {
1651
case CKM_RSA_PKCS:
1652
alg = hx509_signature_rsa_pkcs1_x509();
1653
break;
1654
default:
1655
ret = CKR_FUNCTION_NOT_SUPPORTED;
1656
goto out;
1657
}
1658
1659
sig.data = pData;
1660
sig.length = ulDataLen;
1661
data.data = pSignature;
1662
data.length = ulSignatureLen;
1663
1664
hret = _hx509_verify_signature(context,
1665
o->cert,
1666
alg,
1667
&data,
1668
&sig);
1669
if (hret) {
1670
ret = CKR_GENERAL_ERROR;
1671
goto out;
1672
}
1673
ret = CKR_OK;
1674
1675
out:
1676
return ret;
1677
}
1678
1679
1680
CK_RV
1681
C_VerifyUpdate(CK_SESSION_HANDLE hSession,
1682
CK_BYTE_PTR pPart,
1683
CK_ULONG ulPartLen)
1684
{
1685
INIT_CONTEXT();
1686
st_logf("VerifyUpdate\n");
1687
VERIFY_SESSION_HANDLE(hSession, NULL);
1688
return CKR_FUNCTION_NOT_SUPPORTED;
1689
}
1690
1691
CK_RV
1692
C_VerifyFinal(CK_SESSION_HANDLE hSession,
1693
CK_BYTE_PTR pSignature,
1694
CK_ULONG ulSignatureLen)
1695
{
1696
INIT_CONTEXT();
1697
st_logf("VerifyFinal\n");
1698
VERIFY_SESSION_HANDLE(hSession, NULL);
1699
return CKR_FUNCTION_NOT_SUPPORTED;
1700
}
1701
1702
CK_RV
1703
C_GenerateRandom(CK_SESSION_HANDLE hSession,
1704
CK_BYTE_PTR RandomData,
1705
CK_ULONG ulRandomLen)
1706
{
1707
INIT_CONTEXT();
1708
st_logf("GenerateRandom\n");
1709
VERIFY_SESSION_HANDLE(hSession, NULL);
1710
return CKR_FUNCTION_NOT_SUPPORTED;
1711
}
1712
1713
1714
CK_FUNCTION_LIST funcs = {
1715
{ 2, 11 },
1716
C_Initialize,
1717
C_Finalize,
1718
C_GetInfo,
1719
C_GetFunctionList,
1720
C_GetSlotList,
1721
C_GetSlotInfo,
1722
C_GetTokenInfo,
1723
C_GetMechanismList,
1724
C_GetMechanismInfo,
1725
C_InitToken,
1726
(void *)func_not_supported, /* C_InitPIN */
1727
(void *)func_not_supported, /* C_SetPIN */
1728
C_OpenSession,
1729
C_CloseSession,
1730
C_CloseAllSessions,
1731
C_GetSessionInfo,
1732
(void *)func_not_supported, /* C_GetOperationState */
1733
(void *)func_not_supported, /* C_SetOperationState */
1734
C_Login,
1735
C_Logout,
1736
(void *)func_not_supported, /* C_CreateObject */
1737
(void *)func_not_supported, /* C_CopyObject */
1738
(void *)func_not_supported, /* C_DestroyObject */
1739
(void *)func_not_supported, /* C_GetObjectSize */
1740
C_GetAttributeValue,
1741
(void *)func_not_supported, /* C_SetAttributeValue */
1742
C_FindObjectsInit,
1743
C_FindObjects,
1744
C_FindObjectsFinal,
1745
(void *)func_not_supported, /* C_EncryptInit, */
1746
(void *)func_not_supported, /* C_Encrypt, */
1747
(void *)func_not_supported, /* C_EncryptUpdate, */
1748
(void *)func_not_supported, /* C_EncryptFinal, */
1749
(void *)func_not_supported, /* C_DecryptInit, */
1750
(void *)func_not_supported, /* C_Decrypt, */
1751
(void *)func_not_supported, /* C_DecryptUpdate, */
1752
(void *)func_not_supported, /* C_DecryptFinal, */
1753
C_DigestInit,
1754
(void *)func_not_supported, /* C_Digest */
1755
(void *)func_not_supported, /* C_DigestUpdate */
1756
(void *)func_not_supported, /* C_DigestKey */
1757
(void *)func_not_supported, /* C_DigestFinal */
1758
C_SignInit,
1759
C_Sign,
1760
C_SignUpdate,
1761
C_SignFinal,
1762
(void *)func_not_supported, /* C_SignRecoverInit */
1763
(void *)func_not_supported, /* C_SignRecover */
1764
C_VerifyInit,
1765
C_Verify,
1766
C_VerifyUpdate,
1767
C_VerifyFinal,
1768
(void *)func_not_supported, /* C_VerifyRecoverInit */
1769
(void *)func_not_supported, /* C_VerifyRecover */
1770
(void *)func_not_supported, /* C_DigestEncryptUpdate */
1771
(void *)func_not_supported, /* C_DecryptDigestUpdate */
1772
(void *)func_not_supported, /* C_SignEncryptUpdate */
1773
(void *)func_not_supported, /* C_DecryptVerifyUpdate */
1774
(void *)func_not_supported, /* C_GenerateKey */
1775
(void *)func_not_supported, /* C_GenerateKeyPair */
1776
(void *)func_not_supported, /* C_WrapKey */
1777
(void *)func_not_supported, /* C_UnwrapKey */
1778
(void *)func_not_supported, /* C_DeriveKey */
1779
(void *)func_not_supported, /* C_SeedRandom */
1780
C_GenerateRandom,
1781
(void *)func_not_supported, /* C_GetFunctionStatus */
1782
(void *)func_not_supported, /* C_CancelFunction */
1783
(void *)func_not_supported /* C_WaitForSlotEvent */
1784
};
1785
1786