4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
30 #include <sys/types.h>
31 #include <security/cryptoki.h>
32 #include <cryptoutil.h>
33 #include "softGlobal.h"
34 #include "softSession.h"
35 #include "softObject.h"
39 #include "softCrypt.h"
42 * Allocate a DSA context for the active sign or verify operation.
43 * This function is called without the session lock held.
46 soft_dsa_sign_verify_init_common(soft_session_t
*session_p
,
47 CK_MECHANISM_PTR pMechanism
, soft_object_t
*key_p
,
51 soft_dsa_ctx_t
*dsa_ctx
;
52 CK_MECHANISM digest_mech
;
53 soft_object_t
*tmp_key
= NULL
;
57 if ((key_p
->class != CKO_PRIVATE_KEY
) ||
58 (key_p
->key_type
!= CKK_DSA
))
59 return (CKR_KEY_TYPE_INCONSISTENT
);
61 if ((key_p
->class != CKO_PUBLIC_KEY
) ||
62 (key_p
->key_type
!= CKK_DSA
))
63 return (CKR_KEY_TYPE_INCONSISTENT
);
66 if (pMechanism
->mechanism
== CKM_DSA_SHA1
) {
67 digest_mech
.mechanism
= CKM_SHA_1
;
68 rv
= soft_digest_init_internal(session_p
, &digest_mech
);
73 dsa_ctx
= malloc(sizeof (soft_dsa_ctx_t
));
75 if (dsa_ctx
== NULL
) {
76 return (CKR_HOST_MEMORY
);
80 * Make a copy of the signature or verification key, and save it
81 * in the DSA crypto context since it will be used later for
82 * signing/verification. We don't want to hold any object reference
83 * on this original key while doing signing/verification.
85 (void) pthread_mutex_lock(&key_p
->object_mutex
);
86 rv
= soft_copy_object(key_p
, &tmp_key
, SOFT_COPY_OBJ_ORIG_SH
,
89 if ((rv
!= CKR_OK
) || (tmp_key
== NULL
)) {
90 /* Most likely we ran out of space. */
91 (void) pthread_mutex_unlock(&key_p
->object_mutex
);
96 /* No need to hold the lock on the old object. */
97 (void) pthread_mutex_unlock(&key_p
->object_mutex
);
98 dsa_ctx
->key
= tmp_key
;
100 (void) pthread_mutex_lock(&session_p
->session_mutex
);
103 session_p
->sign
.context
= dsa_ctx
;
104 session_p
->sign
.mech
.mechanism
= pMechanism
->mechanism
;
106 session_p
->verify
.context
= dsa_ctx
;
107 session_p
->verify
.mech
.mechanism
= pMechanism
->mechanism
;
110 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
117 local_dsa_sign(soft_object_t
*key
, CK_BYTE_PTR in
, CK_ULONG inlen
,
121 uchar_t q
[MAX_KEY_ATTR_BUFLEN
];
122 uchar_t p
[MAX_KEY_ATTR_BUFLEN
];
123 uchar_t g
[MAX_KEY_ATTR_BUFLEN
];
124 uchar_t x
[MAX_KEY_ATTR_BUFLEN
];
125 uint_t qlen
= sizeof (q
);
126 uint_t plen
= sizeof (p
);
127 uint_t glen
= sizeof (g
);
128 uint_t xlen
= sizeof (x
);
131 rv
= soft_get_private_value(key
, CKA_PRIME
, p
, &plen
);
136 rv
= soft_get_private_value(key
, CKA_SUBPRIME
, q
, &qlen
);
141 rv
= soft_get_private_value(key
, CKA_BASE
, g
, &glen
);
146 rv
= soft_get_private_value(key
, CKA_VALUE
, x
, &xlen
);
152 k
.prime_bits
= CRYPTO_BYTES2BITS(plen
);
154 k
.subprime_bits
= CRYPTO_BYTES2BITS(qlen
);
157 k
.private_x_bits
= CRYPTO_BYTES2BITS(xlen
);
161 rv
= dsa_sign(&k
, in
, inlen
, out
);
168 local_dsa_verify(soft_object_t
*key
, CK_BYTE_PTR data
, CK_BYTE_PTR sig
)
171 uchar_t g
[MAX_KEY_ATTR_BUFLEN
];
172 uchar_t y
[MAX_KEY_ATTR_BUFLEN
];
173 uchar_t p
[MAX_KEY_ATTR_BUFLEN
];
174 uchar_t q
[MAX_KEY_ATTR_BUFLEN
];
175 uint_t glen
= sizeof (g
);
176 uint_t ylen
= sizeof (y
);
177 uint_t plen
= sizeof (p
);
178 uint_t qlen
= sizeof (q
);
181 rv
= soft_get_public_value(key
, CKA_PRIME
, p
, &plen
);
186 rv
= soft_get_public_value(key
, CKA_SUBPRIME
, q
, &qlen
);
191 rv
= soft_get_public_value(key
, CKA_BASE
, g
, &glen
);
196 rv
= soft_get_public_value(key
, CKA_VALUE
, y
, &ylen
);
202 k
.prime_bits
= CRYPTO_BYTES2BITS(plen
);
204 k
.subprime_bits
= CRYPTO_BYTES2BITS(qlen
);
207 k
.public_y_bits
= CRYPTO_BYTES2BITS(ylen
);
211 rv
= dsa_verify(&k
, data
, sig
);
219 soft_dsa_digest_sign_common(soft_session_t
*session_p
, CK_BYTE_PTR pData
,
220 CK_ULONG ulDataLen
, CK_BYTE_PTR pSigned
,
221 CK_ULONG_PTR pulSignedLen
, boolean_t Final
)
225 CK_BYTE hash
[SHA1_HASH_SIZE
]; /* space enough for SHA1 and MD5 */
226 CK_ULONG hash_len
= SHA1_HASH_SIZE
;
227 soft_dsa_ctx_t
*dsa_ctx
= session_p
->sign
.context
;
228 soft_object_t
*key
= dsa_ctx
->key
;
230 /* Check arguments before performing message digest. */
231 if (pSigned
== NULL
) {
232 /* Application asks for the length of the output buffer. */
233 *pulSignedLen
= DSA_SIGNATURE_LENGTH
;
237 /* Is the application-supplied buffer large enough? */
238 if (*pulSignedLen
< DSA_SIGNATURE_LENGTH
) {
239 *pulSignedLen
= DSA_SIGNATURE_LENGTH
;
240 rv
= CKR_BUFFER_TOO_SMALL
;
245 rv
= soft_digest_final(session_p
, hash
, &hash_len
);
247 rv
= soft_digest(session_p
, pData
, ulDataLen
, hash
, &hash_len
);
251 /* free the signature key */
252 soft_cleanup_object(key
);
258 * Now, we are ready to sign the data
259 * soft_dsa_sign() will free the signature key.
261 rv
= soft_dsa_sign(session_p
, hash
, hash_len
, pSigned
, pulSignedLen
);
264 (void) pthread_mutex_lock(&session_p
->session_mutex
);
265 /* soft_digest_common() has freed the digest context */
266 session_p
->digest
.flags
= 0;
267 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
275 soft_dsa_sign(soft_session_t
*session_p
, CK_BYTE_PTR pData
,
276 CK_ULONG ulDataLen
, CK_BYTE_PTR pSigned
,
277 CK_ULONG_PTR pulSignedLen
)
281 soft_dsa_ctx_t
*dsa_ctx
= session_p
->sign
.context
;
282 soft_object_t
*key
= dsa_ctx
->key
;
284 if ((key
->class != CKO_PRIVATE_KEY
) || (key
->key_type
!= CKK_DSA
)) {
285 rv
= CKR_KEY_TYPE_INCONSISTENT
;
289 /* Output length is always 40 bytes. */
290 if (pSigned
== NULL
) {
291 /* Application asks for the length of the output buffer. */
292 *pulSignedLen
= DSA_SIGNATURE_LENGTH
;
296 /* Input data length needs to be 20 bytes. */
297 if (ulDataLen
!= DSA_SUBPRIME_BYTES
) {
298 rv
= CKR_DATA_LEN_RANGE
;
302 if (*pulSignedLen
< DSA_SIGNATURE_LENGTH
) {
303 *pulSignedLen
= DSA_SIGNATURE_LENGTH
;
304 return (CKR_BUFFER_TOO_SMALL
);
307 rv
= local_dsa_sign(key
, pData
, ulDataLen
, pSigned
);
309 *pulSignedLen
= DSA_SIGNATURE_LENGTH
;
313 (void) pthread_mutex_lock(&session_p
->session_mutex
);
314 free(session_p
->sign
.context
);
315 session_p
->sign
.context
= NULL
;
316 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
317 soft_cleanup_object(key
);
324 soft_dsa_verify(soft_session_t
*session_p
, CK_BYTE_PTR pData
,
325 CK_ULONG ulDataLen
, CK_BYTE_PTR pSignature
,
326 CK_ULONG ulSignatureLen
)
330 soft_dsa_ctx_t
*dsa_ctx
= session_p
->verify
.context
;
331 soft_object_t
*key
= dsa_ctx
->key
;
333 if ((key
->class != CKO_PUBLIC_KEY
) ||(key
->key_type
!= CKK_DSA
)) {
334 rv
= CKR_KEY_TYPE_INCONSISTENT
;
338 /* Input data length needs to be 20 bytes. */
339 if (ulDataLen
!= DSA_SUBPRIME_BYTES
) {
340 rv
= CKR_DATA_LEN_RANGE
;
344 /* The signature length is always 40 bytes. */
345 if (ulSignatureLen
!= DSA_SIGNATURE_LENGTH
) {
346 rv
= CKR_SIGNATURE_LEN_RANGE
;
350 rv
= local_dsa_verify(key
, pData
, pSignature
);
353 (void) pthread_mutex_lock(&session_p
->session_mutex
);
354 free(session_p
->verify
.context
);
355 session_p
->verify
.context
= NULL
;
356 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
357 soft_cleanup_object(key
);
364 soft_dsa_digest_verify_common(soft_session_t
*session_p
, CK_BYTE_PTR pData
,
365 CK_ULONG ulDataLen
, CK_BYTE_PTR pSigned
,
366 CK_ULONG ulSignedLen
, boolean_t Final
)
370 CK_BYTE hash
[SHA1_HASH_SIZE
]; /* space enough for SHA1 and MD5 */
371 CK_ULONG hash_len
= SHA1_HASH_SIZE
;
372 soft_dsa_ctx_t
*dsa_ctx
= session_p
->verify
.context
;
373 soft_object_t
*key
= dsa_ctx
->key
;
376 rv
= soft_digest_final(session_p
, hash
, &hash_len
);
378 rv
= soft_digest(session_p
, pData
, ulDataLen
, hash
, &hash_len
);
382 /* free the verification key */
383 soft_cleanup_object(key
);
389 * Now, we are ready to verify the data using signature.
390 * soft_dsa_verify() will free the verification key.
392 rv
= soft_dsa_verify(session_p
, hash
, hash_len
,
393 pSigned
, ulSignedLen
);
396 (void) pthread_mutex_lock(&session_p
->session_mutex
);
397 /* soft_digest_common() has freed the digest context */
398 session_p
->digest
.flags
= 0;
399 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
405 soft_genDSAkey_set_attribute(soft_object_t
*key
, CK_ATTRIBUTE_TYPE type
,
406 uchar_t
*value
, uint32_t value_len
, boolean_t
public)
410 biginteger_t
*dst
= NULL
;
417 dst
= OBJ_PUB_DSA_VALUE(key
);
419 dst
= OBJ_PRI_DSA_VALUE(key
);
424 dst
= OBJ_PUB_DSA_PRIME(key
);
426 dst
= OBJ_PRI_DSA_PRIME(key
);
431 dst
= OBJ_PUB_DSA_SUBPRIME(key
);
433 dst
= OBJ_PRI_DSA_SUBPRIME(key
);
438 dst
= OBJ_PUB_DSA_BASE(key
);
440 dst
= OBJ_PRI_DSA_BASE(key
);
444 /* Note: removal of preceding 0x00 imitates similar code in RSA */
445 while (value
[0] == 0) { /* remove preceding 0x00 */
450 if ((rv
= dup_bigint_attr(&src
, value
, value_len
)) != CKR_OK
)
453 /* Copy the attribute in the key object. */
454 copy_bigint_attr(&src
, dst
);
457 /* No need to free big_value because dst holds it now after copy. */
464 soft_dsa_genkey_pair(soft_object_t
*pubkey
, soft_object_t
*prikey
)
467 uchar_t prime
[MAX_KEY_ATTR_BUFLEN
];
468 uint32_t prime_len
= sizeof (prime
);
469 uchar_t subprime
[MAX_KEY_ATTR_BUFLEN
];
470 uint32_t subprime_len
= sizeof (subprime
);
471 uchar_t base
[MAX_KEY_ATTR_BUFLEN
];
472 uint32_t base_len
= sizeof (base
);
473 uchar_t pubvalue
[MAX_KEY_ATTR_BUFLEN
];
474 uint32_t pubvalue_len
= sizeof (pubvalue
);
475 uchar_t privalue
[DSA_SUBPRIME_BYTES
];
476 uint32_t privalue_len
= sizeof (privalue
);
479 if ((pubkey
== NULL
) || (prikey
== NULL
)) {
480 return (CKR_ARGUMENTS_BAD
);
483 /* lookup prime, subprime and base */
484 rv
= soft_get_public_value(pubkey
, CKA_PRIME
, prime
, &prime_len
);
486 rv
= CKR_TEMPLATE_INCOMPLETE
;
490 rv
= soft_get_public_value(pubkey
, CKA_SUBPRIME
, subprime
,
493 rv
= CKR_TEMPLATE_INCOMPLETE
;
497 rv
= soft_get_public_value(pubkey
, CKA_BASE
, base
, &base_len
);
499 rv
= CKR_TEMPLATE_INCOMPLETE
;
503 /* Inputs to DSA key pair generation. */
505 k
.prime_bits
= CRYPTO_BYTES2BITS(prime_len
);
506 k
.subprime
= subprime
;
507 k
.subprime_bits
= CRYPTO_BYTES2BITS(subprime_len
);
509 k
.base_bytes
= base_len
;
510 k
.rfunc
= (IS_TOKEN_OBJECT(pubkey
) || IS_TOKEN_OBJECT(prikey
)) ?
511 pkcs11_get_random
: pkcs11_get_urandom
;
513 /* Outputs from DSA key pair generation. */
514 k
.public_y
= pubvalue
;
515 k
.public_y_bits
= CRYPTO_BYTES2BITS(pubvalue_len
);
516 k
.private_x
= privalue
;
517 k
.private_x_bits
= CRYPTO_BYTES2BITS(privalue_len
);
519 rv
= dsa_genkey_pair(&k
);
525 /* Update attribute in public key. */
526 if ((rv
= soft_genDSAkey_set_attribute(pubkey
, CKA_VALUE
,
527 pubvalue
, CRYPTO_BITS2BYTES(k
.public_y_bits
), B_TRUE
)) != CKR_OK
) {
530 /* Update attributes in private key. */
531 if ((rv
= soft_genDSAkey_set_attribute(prikey
, CKA_PRIME
,
532 prime
, CRYPTO_BITS2BYTES(k
.prime_bits
), B_FALSE
)) != CKR_OK
) {
536 if ((rv
= soft_genDSAkey_set_attribute(prikey
, CKA_SUBPRIME
, subprime
,
537 CRYPTO_BITS2BYTES(k
.subprime_bits
), B_FALSE
)) != CKR_OK
) {
541 if ((rv
= soft_genDSAkey_set_attribute(prikey
, CKA_BASE
,
542 base
, k
.base_bytes
, B_FALSE
)) != CKR_OK
) {
546 if ((rv
= soft_genDSAkey_set_attribute(prikey
, CKA_VALUE
, privalue
,
547 CRYPTO_BITS2BYTES(k
.private_x_bits
), B_FALSE
)) != CKR_OK
) {