1 /* $NetBSD: pkcs11gost_link.c,v 1.1.1.5 2015/07/08 15:38:01 christos Exp $ */
4 * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
23 #if defined(PKCS11CRYPTO) && defined(HAVE_PKCS11_GOST)
25 #include <isc/entropy.h>
28 #include <isc/string.h>
31 #include <dns/keyvalues.h>
33 #include <dst/result.h>
35 #include "dst_internal.h"
36 #include "dst_parse.h"
37 #include "dst_pkcs11.h"
40 #include <pk11/pk11.h>
41 #include <pk11/internal.h>
42 #define WANT_GOST_PARAMS
43 #include <pk11/constants.h>
45 #include <pkcs11/pkcs11.h>
48 * RU CryptoPro GOST keys:
51 * CKM_GOSTR3410_WITH_GOSTR3411
52 * CKM_GOSTR3410_KEY_PAIR_GEN
54 * CKA_GOSTR3410_PARAMS (fixed BER OID 1.2.643.2.2.35.1)
55 * CKA_GOSTR3411_PARAMS (fixed BER OID 1.2.643.2.2.30.1)
56 * CKA_GOST28147_PARAMS (optional, don't use)
58 * object class CKO_PUBLIC_KEY
59 * key type CKK_GOSTR3410
60 * attribute CKA_VALUE (point Q)
61 * attribute CKA_GOSTR3410_PARAMS
62 * attribute CKA_GOSTR3411_PARAMS
63 * attribute CKA_GOST28147_PARAMS
65 * object class CKO_PRIVATE_KEY
66 * key type CKK_GOSTR3410
67 * attribute CKA_VALUE (big int d)
68 * attribute CKA_GOSTR3410_PARAMS
69 * attribute CKA_GOSTR3411_PARAMS
70 * attribute CKA_GOST28147_PARAMS
71 * point format: <x> <y> (little endian)
74 #define CKA_VALUE2 CKA_PRIVATE_EXPONENT
76 #define ISC_GOST_SIGNATURELENGTH 64
77 #define ISC_GOST_PUBKEYLENGTH 64
78 #define ISC_GOST_KEYSIZE 256
83 isc_gost_init(isc_gost_t
*ctx
) {
85 CK_MECHANISM mech
= { CKM_GOSTR3411
, NULL
, 0 };
86 int ret
= ISC_R_SUCCESS
;
88 ret
= pk11_get_session(ctx
, OP_GOST
, ISC_TRUE
, ISC_FALSE
,
90 if (ret
!= ISC_R_SUCCESS
)
92 PK11_CALL(pkcs_C_DigestInit
, (ctx
->session
, &mech
), ISC_R_FAILURE
);
97 isc_gost_invalidate(isc_gost_t
*ctx
) {
98 CK_BYTE garbage
[ISC_GOST_DIGESTLENGTH
];
99 CK_ULONG len
= ISC_GOST_DIGESTLENGTH
;
101 if (ctx
->handle
== NULL
)
103 (void) pkcs_C_DigestFinal(ctx
->session
, garbage
, &len
);
104 memset(garbage
, 0, sizeof(garbage
));
105 pk11_return_session(ctx
);
109 isc_gost_update(isc_gost_t
*ctx
, const unsigned char *buf
, unsigned int len
) {
112 int ret
= ISC_R_SUCCESS
;
114 DE_CONST(buf
, pPart
);
115 PK11_CALL(pkcs_C_DigestUpdate
,
116 (ctx
->session
, pPart
, (CK_ULONG
) len
),
122 isc_gost_final(isc_gost_t
*ctx
, unsigned char *digest
) {
124 CK_ULONG len
= ISC_GOST_DIGESTLENGTH
;
125 int ret
= ISC_R_SUCCESS
;
127 PK11_CALL(pkcs_C_DigestFinal
,
128 (ctx
->session
, (CK_BYTE_PTR
) digest
, &len
),
130 pk11_return_session(ctx
);
136 static CK_BBOOL truevalue
= TRUE
;
137 static CK_BBOOL falsevalue
= FALSE
;
139 #define DST_RET(a) {ret = a; goto err;}
141 static isc_result_t
pkcs11gost_todns(const dst_key_t
*key
, isc_buffer_t
*data
);
142 static void pkcs11gost_destroy(dst_key_t
*key
);
145 pkcs11gost_createctx_sign(dst_key_t
*key
, dst_context_t
*dctx
) {
147 CK_MECHANISM mech
= { CKM_GOSTR3410_WITH_GOSTR3411
, NULL
, 0 };
148 CK_OBJECT_CLASS keyClass
= CKO_PRIVATE_KEY
;
149 CK_KEY_TYPE keyType
= CKK_GOSTR3410
;
150 CK_ATTRIBUTE keyTemplate
[] =
152 { CKA_CLASS
, &keyClass
, (CK_ULONG
) sizeof(keyClass
) },
153 { CKA_KEY_TYPE
, &keyType
, (CK_ULONG
) sizeof(keyType
) },
154 { CKA_TOKEN
, &falsevalue
, (CK_ULONG
) sizeof(falsevalue
) },
155 { CKA_PRIVATE
, &falsevalue
, (CK_ULONG
) sizeof(falsevalue
) },
156 { CKA_SENSITIVE
, &falsevalue
, (CK_ULONG
) sizeof(falsevalue
) },
157 { CKA_SIGN
, &truevalue
, (CK_ULONG
) sizeof(truevalue
) },
158 { CKA_VALUE
, NULL
, 0 },
159 { CKA_GOSTR3410_PARAMS
, pk11_gost_a_paramset
,
160 (CK_ULONG
) sizeof(pk11_gost_a_paramset
) },
161 { CKA_GOSTR3411_PARAMS
, pk11_gost_paramset
,
162 (CK_ULONG
) sizeof(pk11_gost_paramset
) }
166 pk11_context_t
*pk11_ctx
;
170 pk11_ctx
= (pk11_context_t
*) isc_mem_get(dctx
->mctx
,
172 if (pk11_ctx
== NULL
)
173 return (ISC_R_NOMEMORY
);
174 ret
= pk11_get_session(pk11_ctx
, OP_GOST
, ISC_TRUE
, ISC_FALSE
,
175 ISC_FALSE
, NULL
, pk11_get_best_token(OP_GOST
));
176 if (ret
!= ISC_R_SUCCESS
)
179 gost
= key
->keydata
.pkey
;
180 if (gost
->ontoken
&& (gost
->object
!= CK_INVALID_HANDLE
)) {
181 pk11_ctx
->ontoken
= gost
->ontoken
;
182 pk11_ctx
->object
= gost
->object
;
186 for (attr
= pk11_attribute_first(gost
);
188 attr
= pk11_attribute_next(gost
, attr
))
189 switch (attr
->type
) {
191 INSIST(keyTemplate
[6].type
== CKA_VALUE
);
192 keyTemplate
[6].pValue
= isc_mem_get(dctx
->mctx
,
194 if (keyTemplate
[6].pValue
== NULL
)
195 DST_RET(ISC_R_NOMEMORY
);
196 memmove(keyTemplate
[6].pValue
, attr
->pValue
,
198 keyTemplate
[6].ulValueLen
= attr
->ulValueLen
;
201 pk11_ctx
->object
= CK_INVALID_HANDLE
;
202 pk11_ctx
->ontoken
= ISC_FALSE
;
203 PK11_RET(pkcs_C_CreateObject
,
205 keyTemplate
, (CK_ULONG
) 9,
211 PK11_RET(pkcs_C_SignInit
,
212 (pk11_ctx
->session
, &mech
, pk11_ctx
->object
),
215 dctx
->ctxdata
.pk11_ctx
= pk11_ctx
;
217 for (i
= 6; i
<= 6; i
++)
218 if (keyTemplate
[i
].pValue
!= NULL
) {
219 memset(keyTemplate
[i
].pValue
, 0,
220 keyTemplate
[i
].ulValueLen
);
221 isc_mem_put(dctx
->mctx
,
222 keyTemplate
[i
].pValue
,
223 keyTemplate
[i
].ulValueLen
);
226 return (ISC_R_SUCCESS
);
229 if (!pk11_ctx
->ontoken
&& (pk11_ctx
->object
!= CK_INVALID_HANDLE
))
230 (void) pkcs_C_DestroyObject(pk11_ctx
->session
, pk11_ctx
->object
);
231 for (i
= 6; i
<= 6; i
++)
232 if (keyTemplate
[i
].pValue
!= NULL
) {
233 memset(keyTemplate
[i
].pValue
, 0,
234 keyTemplate
[i
].ulValueLen
);
235 isc_mem_put(dctx
->mctx
,
236 keyTemplate
[i
].pValue
,
237 keyTemplate
[i
].ulValueLen
);
239 pk11_return_session(pk11_ctx
);
240 memset(pk11_ctx
, 0, sizeof(*pk11_ctx
));
241 isc_mem_put(dctx
->mctx
, pk11_ctx
, sizeof(*pk11_ctx
));
247 pkcs11gost_createctx_verify(dst_key_t
*key
, dst_context_t
*dctx
) {
249 CK_MECHANISM mech
= { CKM_GOSTR3410_WITH_GOSTR3411
, NULL
, 0 };
250 CK_OBJECT_CLASS keyClass
= CKO_PUBLIC_KEY
;
251 CK_KEY_TYPE keyType
= CKK_GOSTR3410
;
252 CK_ATTRIBUTE keyTemplate
[] =
254 { CKA_CLASS
, &keyClass
, (CK_ULONG
) sizeof(keyClass
) },
255 { CKA_KEY_TYPE
, &keyType
, (CK_ULONG
) sizeof(keyType
) },
256 { CKA_TOKEN
, &falsevalue
, (CK_ULONG
) sizeof(falsevalue
) },
257 { CKA_PRIVATE
, &falsevalue
, (CK_ULONG
) sizeof(falsevalue
) },
258 { CKA_VERIFY
, &truevalue
, (CK_ULONG
) sizeof(truevalue
) },
259 { CKA_VALUE
, NULL
, 0 },
260 { CKA_GOSTR3410_PARAMS
, pk11_gost_a_paramset
,
261 (CK_ULONG
) sizeof(pk11_gost_a_paramset
) },
262 { CKA_GOSTR3411_PARAMS
, pk11_gost_paramset
,
263 (CK_ULONG
) sizeof(pk11_gost_paramset
) }
267 pk11_context_t
*pk11_ctx
;
271 pk11_ctx
= (pk11_context_t
*) isc_mem_get(dctx
->mctx
,
273 if (pk11_ctx
== NULL
)
274 return (ISC_R_NOMEMORY
);
275 ret
= pk11_get_session(pk11_ctx
, OP_GOST
, ISC_TRUE
, ISC_FALSE
,
276 ISC_FALSE
, NULL
, pk11_get_best_token(OP_GOST
));
277 if (ret
!= ISC_R_SUCCESS
)
280 gost
= key
->keydata
.pkey
;
281 if (gost
->ontoken
&& (gost
->object
!= CK_INVALID_HANDLE
)) {
282 pk11_ctx
->ontoken
= gost
->ontoken
;
283 pk11_ctx
->object
= gost
->object
;
287 for (attr
= pk11_attribute_first(gost
);
289 attr
= pk11_attribute_next(gost
, attr
))
290 switch (attr
->type
) {
292 INSIST(keyTemplate
[5].type
== attr
->type
);
293 keyTemplate
[5].pValue
= isc_mem_get(dctx
->mctx
,
295 if (keyTemplate
[5].pValue
== NULL
)
296 DST_RET(ISC_R_NOMEMORY
);
297 memmove(keyTemplate
[5].pValue
, attr
->pValue
,
299 keyTemplate
[5].ulValueLen
= attr
->ulValueLen
;
302 pk11_ctx
->object
= CK_INVALID_HANDLE
;
303 pk11_ctx
->ontoken
= ISC_FALSE
;
304 PK11_RET(pkcs_C_CreateObject
,
306 keyTemplate
, (CK_ULONG
) 8,
312 PK11_RET(pkcs_C_VerifyInit
,
313 (pk11_ctx
->session
, &mech
, pk11_ctx
->object
),
316 dctx
->ctxdata
.pk11_ctx
= pk11_ctx
;
318 for (i
= 5; i
<= 5; i
++)
319 if (keyTemplate
[i
].pValue
!= NULL
) {
320 memset(keyTemplate
[i
].pValue
, 0,
321 keyTemplate
[i
].ulValueLen
);
322 isc_mem_put(dctx
->mctx
,
323 keyTemplate
[i
].pValue
,
324 keyTemplate
[i
].ulValueLen
);
327 return (ISC_R_SUCCESS
);
330 if (!pk11_ctx
->ontoken
&& (pk11_ctx
->object
!= CK_INVALID_HANDLE
))
331 (void) pkcs_C_DestroyObject(pk11_ctx
->session
, pk11_ctx
->object
);
332 for (i
= 5; i
<= 5; i
++)
333 if (keyTemplate
[i
].pValue
!= NULL
) {
334 memset(keyTemplate
[i
].pValue
, 0,
335 keyTemplate
[i
].ulValueLen
);
336 isc_mem_put(dctx
->mctx
,
337 keyTemplate
[i
].pValue
,
338 keyTemplate
[i
].ulValueLen
);
340 pk11_return_session(pk11_ctx
);
341 memset(pk11_ctx
, 0, sizeof(*pk11_ctx
));
342 isc_mem_put(dctx
->mctx
, pk11_ctx
, sizeof(*pk11_ctx
));
348 pkcs11gost_createctx(dst_key_t
*key
, dst_context_t
*dctx
) {
349 if (dctx
->use
== DO_SIGN
)
350 return (pkcs11gost_createctx_sign(key
, dctx
));
352 return (pkcs11gost_createctx_verify(key
, dctx
));
356 pkcs11gost_destroyctx(dst_context_t
*dctx
) {
357 pk11_context_t
*pk11_ctx
= dctx
->ctxdata
.pk11_ctx
;
359 if (pk11_ctx
!= NULL
) {
360 if (!pk11_ctx
->ontoken
&&
361 (pk11_ctx
->object
!= CK_INVALID_HANDLE
))
362 (void) pkcs_C_DestroyObject(pk11_ctx
->session
,
364 pk11_return_session(pk11_ctx
);
365 memset(pk11_ctx
, 0, sizeof(*pk11_ctx
));
366 isc_mem_put(dctx
->mctx
, pk11_ctx
, sizeof(*pk11_ctx
));
367 dctx
->ctxdata
.pk11_ctx
= NULL
;
372 pkcs11gost_adddata(dst_context_t
*dctx
, const isc_region_t
*data
) {
374 pk11_context_t
*pk11_ctx
= dctx
->ctxdata
.pk11_ctx
;
375 isc_result_t ret
= ISC_R_SUCCESS
;
377 if (dctx
->use
== DO_SIGN
)
378 PK11_CALL(pkcs_C_SignUpdate
,
380 (CK_BYTE_PTR
) data
->base
,
381 (CK_ULONG
) data
->length
),
384 PK11_CALL(pkcs_C_VerifyUpdate
,
386 (CK_BYTE_PTR
) data
->base
,
387 (CK_ULONG
) data
->length
),
393 pkcs11gost_sign(dst_context_t
*dctx
, isc_buffer_t
*sig
) {
395 CK_ULONG siglen
= ISC_GOST_SIGNATURELENGTH
;
397 pk11_context_t
*pk11_ctx
= dctx
->ctxdata
.pk11_ctx
;
398 isc_result_t ret
= ISC_R_SUCCESS
;
400 isc_buffer_availableregion(sig
, &r
);
401 if (r
.length
< ISC_GOST_SIGNATURELENGTH
)
402 return (ISC_R_NOSPACE
);
404 PK11_RET(pkcs_C_SignFinal
,
405 (pk11_ctx
->session
, (CK_BYTE_PTR
) r
.base
, &siglen
),
407 if (siglen
!= ISC_GOST_SIGNATURELENGTH
)
408 return (DST_R_SIGNFAILURE
);
410 isc_buffer_add(sig
, ISC_GOST_SIGNATURELENGTH
);
417 pkcs11gost_verify(dst_context_t
*dctx
, const isc_region_t
*sig
) {
419 pk11_context_t
*pk11_ctx
= dctx
->ctxdata
.pk11_ctx
;
420 isc_result_t ret
= ISC_R_SUCCESS
;
422 PK11_CALL(pkcs_C_VerifyFinal
,
424 (CK_BYTE_PTR
) sig
->base
,
425 (CK_ULONG
) sig
->length
),
426 DST_R_VERIFYFAILURE
);
431 pkcs11gost_compare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
432 pk11_object_t
*gost1
, *gost2
;
433 CK_ATTRIBUTE
*attr1
, *attr2
;
435 gost1
= key1
->keydata
.pkey
;
436 gost2
= key2
->keydata
.pkey
;
438 if ((gost1
== NULL
) && (gost2
== NULL
))
440 else if ((gost1
== NULL
) || (gost2
== NULL
))
443 attr1
= pk11_attribute_bytype(gost1
, CKA_VALUE
);
444 attr2
= pk11_attribute_bytype(gost2
, CKA_VALUE
);
445 if ((attr1
== NULL
) && (attr2
== NULL
))
447 else if ((attr1
== NULL
) || (attr2
== NULL
) ||
448 (attr1
->ulValueLen
!= attr2
->ulValueLen
) ||
449 memcmp(attr1
->pValue
, attr2
->pValue
, attr1
->ulValueLen
))
452 attr1
= pk11_attribute_bytype(gost1
, CKA_VALUE2
);
453 attr2
= pk11_attribute_bytype(gost2
, CKA_VALUE2
);
454 if (((attr1
!= NULL
) || (attr2
!= NULL
)) &&
455 ((attr1
== NULL
) || (attr2
== NULL
) ||
456 (attr1
->ulValueLen
!= attr2
->ulValueLen
) ||
457 memcmp(attr1
->pValue
, attr2
->pValue
, attr1
->ulValueLen
)))
460 if (!gost1
->ontoken
&& !gost2
->ontoken
)
462 else if (gost1
->ontoken
|| gost2
->ontoken
||
463 (gost1
->object
!= gost2
->object
))
470 pkcs11gost_generate(dst_key_t
*key
, int unused
, void (*callback
)(int)) {
472 CK_MECHANISM mech
= { CKM_GOSTR3410_KEY_PAIR_GEN
, NULL
, 0 };
473 CK_KEY_TYPE keyType
= CKK_GOSTR3410
;
474 CK_OBJECT_HANDLE pub
= CK_INVALID_HANDLE
;
475 CK_OBJECT_CLASS pubClass
= CKO_PUBLIC_KEY
;
476 CK_ATTRIBUTE pubTemplate
[] =
478 { CKA_CLASS
, &pubClass
, (CK_ULONG
) sizeof(pubClass
) },
479 { CKA_KEY_TYPE
, &keyType
, (CK_ULONG
) sizeof(keyType
) },
480 { CKA_TOKEN
, &falsevalue
, (CK_ULONG
) sizeof(falsevalue
) },
481 { CKA_PRIVATE
, &falsevalue
, (CK_ULONG
) sizeof(falsevalue
) },
482 { CKA_VERIFY
, &truevalue
, (CK_ULONG
) sizeof(truevalue
) },
483 { CKA_GOSTR3410_PARAMS
, pk11_gost_a_paramset
,
484 (CK_ULONG
) sizeof(pk11_gost_a_paramset
) },
485 { CKA_GOSTR3411_PARAMS
, pk11_gost_paramset
,
486 (CK_ULONG
) sizeof(pk11_gost_paramset
) }
488 CK_OBJECT_HANDLE priv
= CK_INVALID_HANDLE
;
489 CK_OBJECT_HANDLE privClass
= CKO_PRIVATE_KEY
;
490 CK_ATTRIBUTE privTemplate
[] =
492 { CKA_CLASS
, &privClass
, (CK_ULONG
) sizeof(privClass
) },
493 { CKA_KEY_TYPE
, &keyType
, (CK_ULONG
) sizeof(keyType
) },
494 { CKA_TOKEN
, &falsevalue
, (CK_ULONG
) sizeof(falsevalue
) },
495 { CKA_PRIVATE
, &falsevalue
, (CK_ULONG
) sizeof(falsevalue
) },
496 { CKA_SENSITIVE
, &falsevalue
, (CK_ULONG
) sizeof(falsevalue
) },
497 { CKA_EXTRACTABLE
, &truevalue
, (CK_ULONG
) sizeof(truevalue
) },
498 { CKA_SIGN
, &truevalue
, (CK_ULONG
) sizeof(truevalue
) },
502 pk11_context_t
*pk11_ctx
;
508 pk11_ctx
= (pk11_context_t
*) isc_mem_get(key
->mctx
,
510 if (pk11_ctx
== NULL
)
511 return (ISC_R_NOMEMORY
);
512 ret
= pk11_get_session(pk11_ctx
, OP_GOST
, ISC_TRUE
, ISC_FALSE
,
513 ISC_FALSE
, NULL
, pk11_get_best_token(OP_GOST
));
514 if (ret
!= ISC_R_SUCCESS
)
517 PK11_RET(pkcs_C_GenerateKeyPair
,
518 (pk11_ctx
->session
, &mech
,
519 pubTemplate
, (CK_ULONG
) 7,
520 privTemplate
, (CK_ULONG
) 7,
522 DST_R_CRYPTOFAILURE
);
524 gost
= (pk11_object_t
*) isc_mem_get(key
->mctx
, sizeof(*gost
));
526 DST_RET(ISC_R_NOMEMORY
);
527 memset(gost
, 0, sizeof(*gost
));
528 key
->keydata
.pkey
= gost
;
529 key
->key_size
= ISC_GOST_KEYSIZE
;
530 gost
->repr
= (CK_ATTRIBUTE
*) isc_mem_get(key
->mctx
,
532 if (gost
->repr
== NULL
)
533 DST_RET(ISC_R_NOMEMORY
);
534 memset(gost
->repr
, 0, sizeof(*attr
) * 2);
538 attr
[0].type
= CKA_VALUE
;
539 attr
[1].type
= CKA_VALUE2
;
542 PK11_RET(pkcs_C_GetAttributeValue
,
543 (pk11_ctx
->session
, pub
, attr
, 1),
544 DST_R_CRYPTOFAILURE
);
545 attr
->pValue
= isc_mem_get(key
->mctx
, attr
->ulValueLen
);
546 if (attr
->pValue
== NULL
)
547 DST_RET(ISC_R_NOMEMORY
);
548 memset(attr
->pValue
, 0, attr
->ulValueLen
);
549 PK11_RET(pkcs_C_GetAttributeValue
,
550 (pk11_ctx
->session
, pub
, attr
, 1),
551 DST_R_CRYPTOFAILURE
);
554 attr
->type
= CKA_VALUE
;
555 PK11_RET(pkcs_C_GetAttributeValue
,
556 (pk11_ctx
->session
, priv
, attr
, 1),
557 DST_R_CRYPTOFAILURE
);
558 attr
->pValue
= isc_mem_get(key
->mctx
, attr
->ulValueLen
);
559 if (attr
->pValue
== NULL
)
560 DST_RET(ISC_R_NOMEMORY
);
561 memset(attr
->pValue
, 0, attr
->ulValueLen
);
562 PK11_RET(pkcs_C_GetAttributeValue
,
563 (pk11_ctx
->session
, priv
, attr
, 1),
564 DST_R_CRYPTOFAILURE
);
565 attr
->type
= CKA_VALUE2
;
567 (void) pkcs_C_DestroyObject(pk11_ctx
->session
, priv
);
568 (void) pkcs_C_DestroyObject(pk11_ctx
->session
, pub
);
569 pk11_return_session(pk11_ctx
);
570 memset(pk11_ctx
, 0, sizeof(*pk11_ctx
));
571 isc_mem_put(key
->mctx
, pk11_ctx
, sizeof(*pk11_ctx
));
573 return (ISC_R_SUCCESS
);
576 pkcs11gost_destroy(key
);
577 if (priv
!= CK_INVALID_HANDLE
)
578 (void) pkcs_C_DestroyObject(pk11_ctx
->session
, priv
);
579 if (pub
!= CK_INVALID_HANDLE
)
580 (void) pkcs_C_DestroyObject(pk11_ctx
->session
, pub
);
581 pk11_return_session(pk11_ctx
);
582 memset(pk11_ctx
, 0, sizeof(*pk11_ctx
));
583 isc_mem_put(key
->mctx
, pk11_ctx
, sizeof(*pk11_ctx
));
589 pkcs11gost_isprivate(const dst_key_t
*key
) {
590 pk11_object_t
*gost
= key
->keydata
.pkey
;
595 attr
= pk11_attribute_bytype(gost
, CKA_VALUE2
);
596 return (ISC_TF((attr
!= NULL
) || gost
->ontoken
));
600 pkcs11gost_destroy(dst_key_t
*key
) {
601 pk11_object_t
*gost
= key
->keydata
.pkey
;
607 INSIST((gost
->object
== CK_INVALID_HANDLE
) || gost
->ontoken
);
609 for (attr
= pk11_attribute_first(gost
);
611 attr
= pk11_attribute_next(gost
, attr
))
612 switch (attr
->type
) {
615 if (attr
->pValue
!= NULL
) {
616 memset(attr
->pValue
, 0, attr
->ulValueLen
);
617 isc_mem_put(key
->mctx
,
623 if (gost
->repr
!= NULL
) {
624 memset(gost
->repr
, 0, gost
->attrcnt
* sizeof(*attr
));
625 isc_mem_put(key
->mctx
,
627 gost
->attrcnt
* sizeof(*attr
));
629 memset(gost
, 0, sizeof(*gost
));
630 isc_mem_put(key
->mctx
, gost
, sizeof(*gost
));
631 key
->keydata
.pkey
= NULL
;
635 pkcs11gost_todns(const dst_key_t
*key
, isc_buffer_t
*data
) {
640 REQUIRE(key
->keydata
.pkey
!= NULL
);
642 gost
= key
->keydata
.pkey
;
643 attr
= pk11_attribute_bytype(gost
, CKA_VALUE
);
644 if ((attr
== NULL
) || (attr
->ulValueLen
!= ISC_GOST_PUBKEYLENGTH
))
645 return (ISC_R_FAILURE
);
647 isc_buffer_availableregion(data
, &r
);
648 if (r
.length
< ISC_GOST_PUBKEYLENGTH
)
649 return (ISC_R_NOSPACE
);
650 memmove(r
.base
, (CK_BYTE_PTR
) attr
->pValue
, ISC_GOST_PUBKEYLENGTH
);
651 isc_buffer_add(data
, ISC_GOST_PUBKEYLENGTH
);
653 return (ISC_R_SUCCESS
);
657 pkcs11gost_fromdns(dst_key_t
*key
, isc_buffer_t
*data
) {
662 isc_buffer_remainingregion(data
, &r
);
664 return (ISC_R_SUCCESS
);
665 if (r
.length
!= ISC_GOST_PUBKEYLENGTH
)
666 return (DST_R_INVALIDPUBLICKEY
);
668 gost
= (pk11_object_t
*) isc_mem_get(key
->mctx
, sizeof(*gost
));
670 return (ISC_R_NOMEMORY
);
671 memset(gost
, 0, sizeof(*gost
));
672 gost
->repr
= (CK_ATTRIBUTE
*) isc_mem_get(key
->mctx
, sizeof(*attr
));
673 if (gost
->repr
== NULL
)
678 attr
->type
= CKA_VALUE
;
679 attr
->pValue
= isc_mem_get(key
->mctx
, ISC_GOST_PUBKEYLENGTH
);
680 if (attr
->pValue
== NULL
)
682 memmove((CK_BYTE_PTR
) attr
->pValue
, r
.base
, ISC_GOST_PUBKEYLENGTH
);
683 attr
->ulValueLen
= ISC_GOST_PUBKEYLENGTH
;
685 isc_buffer_forward(data
, ISC_GOST_PUBKEYLENGTH
);
686 key
->keydata
.pkey
= gost
;
687 key
->key_size
= ISC_GOST_KEYSIZE
;
688 return (ISC_R_SUCCESS
);
691 for (attr
= pk11_attribute_first(gost
);
693 attr
= pk11_attribute_next(gost
, attr
))
694 switch (attr
->type
) {
696 if (attr
->pValue
!= NULL
) {
697 memset(attr
->pValue
, 0, attr
->ulValueLen
);
698 isc_mem_put(key
->mctx
,
704 if (gost
->repr
!= NULL
) {
705 memset(gost
->repr
, 0, gost
->attrcnt
* sizeof(*attr
));
706 isc_mem_put(key
->mctx
,
708 gost
->attrcnt
* sizeof(*attr
));
710 memset(gost
, 0, sizeof(*gost
));
711 isc_mem_put(key
->mctx
, gost
, sizeof(*gost
));
712 return (ISC_R_NOMEMORY
);
715 static unsigned char gost_private_der
[39] = {
716 0x30, 0x45, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x06,
717 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x13, 0x30,
718 0x12, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02,
719 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02,
720 0x02, 0x1e, 0x01, 0x04, 0x22, 0x02, 0x20
723 #ifdef PREFER_GOSTASN1
726 pkcs11gost_tofile(const dst_key_t
*key
, const char *directory
) {
730 unsigned char *buf
= NULL
;
735 if (key
->keydata
.pkey
== NULL
)
736 return (DST_R_NULLKEY
);
740 return (dst__privstruct_writefile(key
, &priv
, directory
));
743 gost
= key
->keydata
.pkey
;
744 attr
= pk11_attribute_bytype(gost
, CKA_VALUE2
);
746 buf
= isc_mem_get(key
->mctx
, attr
->ulValueLen
+ 39);
748 return (ISC_R_NOMEMORY
);
749 priv
.elements
[i
].tag
= TAG_GOST_PRIVASN1
;
750 priv
.elements
[i
].length
=
751 (unsigned short) attr
->ulValueLen
+ 39;
752 memmove(buf
, gost_private_der
, 39);
753 memmove(buf
+ 39, attr
->pValue
, attr
->ulValueLen
);
754 adj
= (int) attr
->ulValueLen
- 32;
760 priv
.elements
[i
].data
= buf
;
763 return (DST_R_CRYPTOFAILURE
);
766 ret
= dst__privstruct_writefile(key
, &priv
, directory
);
769 memset(buf
, 0, attr
->ulValueLen
);
770 isc_mem_put(key
->mctx
, buf
, attr
->ulValueLen
);
778 pkcs11gost_tofile(const dst_key_t
*key
, const char *directory
) {
782 unsigned char *buf
= NULL
;
786 if (key
->keydata
.pkey
== NULL
)
787 return (DST_R_NULLKEY
);
791 return (dst__privstruct_writefile(key
, &priv
, directory
));
794 gost
= key
->keydata
.pkey
;
795 attr
= pk11_attribute_bytype(gost
, CKA_VALUE2
);
797 buf
= isc_mem_get(key
->mctx
, attr
->ulValueLen
);
799 return (ISC_R_NOMEMORY
);
800 priv
.elements
[i
].tag
= TAG_GOST_PRIVRAW
;
801 priv
.elements
[i
].length
= (unsigned short) attr
->ulValueLen
;
802 memmove(buf
, attr
->pValue
, attr
->ulValueLen
);
803 priv
.elements
[i
].data
= buf
;
806 return (DST_R_CRYPTOFAILURE
);
809 ret
= dst__privstruct_writefile(key
, &priv
, directory
);
812 memset(buf
, 0, attr
->ulValueLen
);
813 isc_mem_put(key
->mctx
, buf
, attr
->ulValueLen
);
820 pkcs11gost_parse(dst_key_t
*key
, isc_lex_t
*lexer
, dst_key_t
*pub
) {
823 pk11_object_t
*gost
= NULL
;
824 CK_ATTRIBUTE
*attr
, *pattr
;
825 isc_mem_t
*mctx
= key
->mctx
;
827 if ((pub
== NULL
) || (pub
->keydata
.pkey
== NULL
))
828 DST_RET(DST_R_INVALIDPRIVATEKEY
);
830 /* read private key file */
831 ret
= dst__privstruct_parse(key
, DST_ALG_ECDSA256
, lexer
, mctx
, &priv
);
832 if (ret
!= ISC_R_SUCCESS
)
836 if (priv
.nelements
!= 0)
837 DST_RET(DST_R_INVALIDPRIVATEKEY
);
839 key
->keydata
.pkey
= pub
->keydata
.pkey
;
840 pub
->keydata
.pkey
= NULL
;
841 key
->key_size
= pub
->key_size
;
843 dst__privstruct_free(&priv
, mctx
);
844 memset(&priv
, 0, sizeof(priv
));
846 return (ISC_R_SUCCESS
);
849 if (priv
.elements
[0].tag
== TAG_GOST_PRIVASN1
) {
850 int adj
= (int) priv
.elements
[0].length
- (39 + 32);
851 unsigned char buf
[39];
853 if ((adj
> 0) || (adj
< -31))
854 DST_RET(DST_R_INVALIDPRIVATEKEY
);
855 memmove(buf
, gost_private_der
, 39);
861 if (memcmp(priv
.elements
[0].data
, buf
, 39) != 0)
862 DST_RET(DST_R_INVALIDPRIVATEKEY
);
863 priv
.elements
[0].tag
= TAG_GOST_PRIVRAW
;
864 priv
.elements
[0].length
-= 39;
865 memmove(priv
.elements
[0].data
,
866 priv
.elements
[0].data
+ 39,
870 gost
= (pk11_object_t
*) isc_mem_get(key
->mctx
, sizeof(*gost
));
872 DST_RET(ISC_R_NOMEMORY
);
873 memset(gost
, 0, sizeof(*gost
));
874 key
->keydata
.pkey
= gost
;
875 key
->key_size
= ISC_GOST_KEYSIZE
;
877 gost
->repr
= (CK_ATTRIBUTE
*) isc_mem_get(key
->mctx
,
879 if (gost
->repr
== NULL
)
880 DST_RET(ISC_R_NOMEMORY
);
881 memset(gost
->repr
, 0, sizeof(*attr
) * 2);
885 attr
->type
= CKA_VALUE
;
886 pattr
= pk11_attribute_bytype(pub
->keydata
.pkey
, CKA_VALUE
);
887 INSIST(pattr
!= NULL
);
888 attr
->pValue
= isc_mem_get(key
->mctx
, pattr
->ulValueLen
);
889 if (attr
->pValue
== NULL
)
890 DST_RET(ISC_R_NOMEMORY
);
891 memmove(attr
->pValue
, pattr
->pValue
, pattr
->ulValueLen
);
892 attr
->ulValueLen
= pattr
->ulValueLen
;
895 attr
->type
= CKA_VALUE2
;
896 attr
->pValue
= isc_mem_get(key
->mctx
, priv
.elements
[0].length
);
897 if (attr
->pValue
== NULL
)
898 DST_RET(ISC_R_NOMEMORY
);
899 memmove(attr
->pValue
, priv
.elements
[0].data
, priv
.elements
[0].length
);
900 attr
->ulValueLen
= priv
.elements
[0].length
;
902 dst__privstruct_free(&priv
, mctx
);
903 memset(&priv
, 0, sizeof(priv
));
905 return (ISC_R_SUCCESS
);
908 pkcs11gost_destroy(key
);
909 dst__privstruct_free(&priv
, mctx
);
910 memset(&priv
, 0, sizeof(priv
));
914 static dst_func_t pkcs11gost_functions
= {
915 pkcs11gost_createctx
,
916 NULL
, /*%< createctx2 */
917 pkcs11gost_destroyctx
,
921 NULL
, /*%< verify2 */
922 NULL
, /*%< computesecret */
924 NULL
, /*%< paramcompare */
926 pkcs11gost_isprivate
,
932 NULL
, /*%< cleanup */
933 NULL
, /*%< fromlabel */
935 NULL
, /*%< restore */
939 dst__pkcs11gost_init(dst_func_t
**funcp
) {
940 REQUIRE(funcp
!= NULL
);
942 *funcp
= &pkcs11gost_functions
;
943 return (ISC_R_SUCCESS
);
946 #else /* PKCS11CRYPTO && HAVE_PKCS11_GOST */
948 #include <isc/util.h>
950 EMPTY_TRANSLATION_UNIT
952 #endif /* PKCS11CRYPTO && HAVE_PKCS11_GOST */