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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
29 #include <sys/types.h>
30 #include <sys/crypto/common.h>
31 #include <security/cryptoki.h>
34 #include "softGlobal.h"
35 #include "softSession.h"
36 #include "softObject.h"
38 #include "softCrypt.h"
43 soft_free_ecparams(ECParams
*params
, boolean_t freeit
)
45 SECITEM_FreeItem(¶ms
->fieldID
.u
.prime
, B_FALSE
);
46 SECITEM_FreeItem(¶ms
->curve
.a
, B_FALSE
);
47 SECITEM_FreeItem(¶ms
->curve
.b
, B_FALSE
);
48 SECITEM_FreeItem(¶ms
->curve
.seed
, B_FALSE
);
49 SECITEM_FreeItem(¶ms
->base
, B_FALSE
);
50 SECITEM_FreeItem(¶ms
->order
, B_FALSE
);
51 SECITEM_FreeItem(¶ms
->DEREncoding
, B_FALSE
);
52 SECITEM_FreeItem(¶ms
->curveOID
, B_FALSE
);
58 soft_free_ecc_context(soft_ecc_ctx_t
*ecc_ctx
)
60 if (ecc_ctx
!= NULL
) {
61 if (ecc_ctx
->key
!= NULL
) {
62 soft_cleanup_object(ecc_ctx
->key
);
66 soft_free_ecparams(&ecc_ctx
->ecparams
, B_FALSE
);
72 soft_free_ecprivkey(ECPrivateKey
*key
)
74 soft_free_ecparams(&key
->ecParams
, B_FALSE
);
76 * Don't free publicValue or privateValue
77 * as these values are copied into objects.
79 SECITEM_FreeItem(&key
->version
, B_FALSE
);
84 * Called from init routines to do basic sanity checks. Init routines,
85 * e.g. sign_init should fail rather than subsequent operations.
88 check_key(soft_object_t
*key_p
, boolean_t sign
)
94 if ((key_p
->class != CKO_PRIVATE_KEY
) ||
95 (key_p
->key_type
!= CKK_EC
))
96 return (CKR_KEY_TYPE_INCONSISTENT
);
98 p
= OBJ_PRI_EC_VALUE(key_p
);
99 len
= p
->big_value_len
;
100 if (p
->big_value
== NULL
)
103 if (len
< CRYPTO_BITS2BYTES(EC_MIN_KEY_LEN
) ||
104 len
> CRYPTO_BITS2BYTES(EC_MAX_KEY_LEN
))
105 return (CKR_KEY_SIZE_RANGE
);
107 if ((key_p
->class != CKO_PUBLIC_KEY
) ||
108 (key_p
->key_type
!= CKK_EC
))
109 return (CKR_KEY_TYPE_INCONSISTENT
);
111 p
= OBJ_PUB_EC_POINT(key_p
);
112 len
= p
->big_value_len
;
113 if (p
->big_value
== NULL
)
116 if (len
< CRYPTO_BITS2BYTES(EC_MIN_KEY_LEN
) * 2 + 1 ||
117 len
> CRYPTO_BITS2BYTES(EC_MAX_KEY_LEN
) * 2 + 1)
118 return (CKR_KEY_SIZE_RANGE
);
125 * This function places the octet string of the specified attribute
126 * into the corresponding key object.
129 soft_genECkey_set_attribute(soft_object_t
*key
, biginteger_t
*bi
,
130 CK_ATTRIBUTE_TYPE type
)
136 dst
= OBJ_PRI_EC_VALUE(key
);
140 dst
= OBJ_PUB_EC_POINT(key
);
143 copy_bigint_attr(bi
, dst
);
147 soft_ec_genkey_pair(soft_object_t
*pubkey
, soft_object_t
*prikey
)
150 CK_ATTRIBUTE
template;
151 ECPrivateKey
*privKey
; /* contains both public and private values */
153 SECKEYECParams params_item
;
155 uchar_t param_buffer
[EC_MAX_OID_LEN
];
158 if ((pubkey
->class != CKO_PUBLIC_KEY
) ||
159 (pubkey
->key_type
!= CKK_EC
))
160 return (CKR_KEY_TYPE_INCONSISTENT
);
162 if ((prikey
->class != CKO_PRIVATE_KEY
) ||
163 (prikey
->key_type
!= CKK_EC
))
164 return (CKR_KEY_TYPE_INCONSISTENT
);
166 template.type
= CKA_EC_PARAMS
;
167 template.pValue
= param_buffer
;
168 template.ulValueLen
= sizeof (param_buffer
);
169 rv
= soft_get_public_key_attribute(pubkey
, &template);
173 paramlen
= template.ulValueLen
;
175 /* private key also has CKA_EC_PARAMS attribute */
176 rv
= set_extra_attr_to_object(prikey
, CKA_EC_PARAMS
, &template);
182 if (param_buffer
[0] != 0x06 ||
183 param_buffer
[1] != paramlen
- 2) {
184 return (CKR_ATTRIBUTE_VALUE_INVALID
);
186 params_item
.len
= paramlen
;
187 params_item
.data
= param_buffer
;
188 if (EC_DecodeParams(¶ms_item
, &ecparams
, 0) != SECSuccess
) {
190 return (CKR_ARGUMENTS_BAD
);
193 if (EC_NewKey(ecparams
, &privKey
, 0) != SECSuccess
) {
194 soft_free_ecparams(ecparams
, B_TRUE
);
195 return (CKR_FUNCTION_FAILED
);
198 bi
.big_value
= privKey
->privateValue
.data
;
199 bi
.big_value_len
= privKey
->privateValue
.len
;
200 soft_genECkey_set_attribute(prikey
, &bi
, CKA_VALUE
);
202 bi
.big_value
= privKey
->publicValue
.data
;
203 bi
.big_value_len
= privKey
->publicValue
.len
;
204 soft_genECkey_set_attribute(pubkey
, &bi
, CKA_EC_POINT
);
206 soft_free_ecprivkey(privKey
);
207 soft_free_ecparams(ecparams
, B_TRUE
);
213 soft_ec_key_derive(soft_object_t
*basekey
, soft_object_t
*secretkey
,
214 void *mech_params
, size_t mech_params_len
)
217 CK_ATTRIBUTE
template;
218 CK_ECDH1_DERIVE_PARAMS
*ecdh1_derive_params
= mech_params
;
219 uchar_t value
[EC_MAX_VALUE_LEN
];
220 uint32_t value_len
= sizeof (value
);
221 uchar_t params
[EC_MAX_OID_LEN
];
222 uint32_t params_len
= sizeof (params
);
225 SECKEYECParams params_item
;
226 SECItem public_value_item
, private_value_item
, secret_item
;
229 if (mech_params_len
!= sizeof (CK_ECDH1_DERIVE_PARAMS
) ||
230 ecdh1_derive_params
->kdf
!= CKD_NULL
) {
231 return (CKR_MECHANISM_PARAM_INVALID
);
234 template.type
= CKA_VALUE
;
235 template.pValue
= value
;
236 template.ulValueLen
= value_len
;
237 rv
= soft_get_private_key_attribute(basekey
, &template);
241 value_len
= template.ulValueLen
;
242 private_value_item
.data
= value
;
243 private_value_item
.len
= value_len
;
245 template.type
= CKA_EC_PARAMS
;
246 template.pValue
= params
;
247 template.ulValueLen
= params_len
;
248 rv
= soft_get_private_key_attribute(basekey
, &template);
252 params_len
= template.ulValueLen
;
254 switch (secretkey
->key_type
) {
256 keylen
= DES_KEYSIZE
;
259 keylen
= DES2_KEYSIZE
;
262 keylen
= DES3_KEYSIZE
;
266 case CKK_GENERIC_SECRET
:
267 keylen
= OBJ_SEC_VALUE_LEN(secretkey
);
272 if (params
[0] != 0x06 ||
273 params
[1] != params_len
- 2) {
274 return (CKR_ATTRIBUTE_VALUE_INVALID
);
276 params_item
.data
= params
;
277 params_item
.len
= params_len
;
278 if (EC_DecodeParams(¶ms_item
, &ecparams
, 0) != SECSuccess
) {
280 return (CKR_ARGUMENTS_BAD
);
283 public_value_item
.data
= ecdh1_derive_params
->pPublicData
;
284 public_value_item
.len
= ecdh1_derive_params
->ulPublicDataLen
;
286 secret_item
.data
= NULL
;
289 if (ECDH_Derive(&public_value_item
, ecparams
, &private_value_item
,
290 B_FALSE
, &secret_item
, 0) != SECSuccess
) {
291 soft_free_ecparams(ecparams
, B_TRUE
);
292 return (CKR_FUNCTION_FAILED
);
298 keylen
= secret_item
.len
;
300 if (keylen
> secret_item
.len
) {
301 rv
= CKR_ATTRIBUTE_VALUE_INVALID
;
304 buf
= malloc(keylen
);
306 rv
= CKR_HOST_MEMORY
;
309 bcopy(secret_item
.data
+ secret_item
.len
- keylen
, buf
, keylen
);
310 OBJ_SEC_VALUE_LEN(secretkey
) = keylen
;
311 OBJ_SEC_VALUE(secretkey
) = buf
;
314 soft_free_ecparams(ecparams
, B_TRUE
);
315 SECITEM_FreeItem(&secret_item
, B_FALSE
);
321 * Allocate a ECC context for the active sign or verify operation.
322 * This function is called without the session lock held.
325 soft_ecc_sign_verify_init_common(soft_session_t
*session_p
,
326 CK_MECHANISM_PTR pMechanism
, soft_object_t
*key_p
,
330 CK_ATTRIBUTE
template;
331 CK_MECHANISM digest_mech
;
332 soft_ecc_ctx_t
*ecc_ctx
;
333 soft_object_t
*tmp_key
= NULL
;
334 uchar_t params
[EC_MAX_OID_LEN
];
336 SECKEYECParams params_item
;
338 if ((rv
= check_key(key_p
, sign
)) != CKR_OK
)
341 if (pMechanism
->mechanism
== CKM_ECDSA_SHA1
) {
342 digest_mech
.mechanism
= CKM_SHA_1
;
343 rv
= soft_digest_init_internal(session_p
, &digest_mech
);
348 ecc_ctx
= malloc(sizeof (soft_ecc_ctx_t
));
349 if (ecc_ctx
== NULL
) {
350 return (CKR_HOST_MEMORY
);
354 * Make a copy of the signature or verification key, and save it
355 * in the ECC crypto context since it will be used later for
356 * signing/verification. We don't want to hold any object reference
357 * on this original key while doing signing/verification.
359 (void) pthread_mutex_lock(&key_p
->object_mutex
);
360 rv
= soft_copy_object(key_p
, &tmp_key
, SOFT_COPY_OBJ_ORIG_SH
, NULL
);
361 if ((rv
!= CKR_OK
) || (tmp_key
== NULL
)) {
362 /* Most likely we ran out of space. */
363 (void) pthread_mutex_unlock(&key_p
->object_mutex
);
369 template.type
= CKA_EC_PARAMS
;
370 template.pValue
= params
;
371 template.ulValueLen
= sizeof (params
);
372 rv
= soft_get_private_key_attribute(key_p
, &template);
373 (void) pthread_mutex_unlock(&key_p
->object_mutex
);
379 if (params
[0] != 0x06 ||
380 params
[1] != template.ulValueLen
- 2) {
381 rv
= CKR_ATTRIBUTE_VALUE_INVALID
;
384 params_item
.data
= params
;
385 params_item
.len
= template.ulValueLen
;
387 ecc_ctx
->key
= tmp_key
;
389 if (EC_DecodeParams(¶ms_item
, &ecparams
, 0) != SECSuccess
) {
391 rv
= CKR_ARGUMENTS_BAD
;
394 ecc_ctx
->ecparams
= *ecparams
;
397 (void) pthread_mutex_lock(&session_p
->session_mutex
);
400 session_p
->sign
.context
= ecc_ctx
;
401 session_p
->sign
.mech
.mechanism
= pMechanism
->mechanism
;
403 session_p
->verify
.context
= ecc_ctx
;
404 session_p
->verify
.mech
.mechanism
= pMechanism
->mechanism
;
407 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
411 soft_cleanup_object(tmp_key
);
419 soft_ecc_digest_sign_common(soft_session_t
*session_p
, CK_BYTE_PTR pData
,
420 CK_ULONG ulDataLen
, CK_BYTE_PTR pSigned
,
421 CK_ULONG_PTR pulSignedLen
, boolean_t Final
)
424 CK_BYTE hash
[SHA1_HASH_SIZE
];
425 CK_ULONG hash_len
= SHA1_HASH_SIZE
;
427 if (pSigned
!= NULL
) {
429 rv
= soft_digest_final(session_p
, hash
, &hash_len
);
431 rv
= soft_digest(session_p
, pData
, ulDataLen
, hash
,
436 (void) pthread_mutex_lock(&session_p
->session_mutex
);
437 soft_free_ecc_context(session_p
->sign
.context
);
438 session_p
->sign
.context
= NULL
;
439 session_p
->digest
.flags
= 0;
440 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
445 rv
= soft_ecc_sign(session_p
, hash
, hash_len
, pSigned
, pulSignedLen
);
448 (void) pthread_mutex_lock(&session_p
->session_mutex
);
449 /* soft_digest_common() has freed the digest context */
450 session_p
->digest
.flags
= 0;
451 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
458 soft_ecc_sign(soft_session_t
*session_p
, CK_BYTE_PTR pData
,
459 CK_ULONG ulDataLen
, CK_BYTE_PTR pSigned
,
460 CK_ULONG_PTR pulSignedLen
)
464 soft_ecc_ctx_t
*ecc_ctx
= session_p
->sign
.context
;
465 soft_object_t
*key
= ecc_ctx
->key
;
466 uchar_t value
[EC_MAX_VALUE_LEN
];
468 SECItem signature_item
;
472 if ((key
->class != CKO_PRIVATE_KEY
) || (key
->key_type
!= CKK_EC
)) {
473 rv
= CKR_KEY_TYPE_INCONSISTENT
;
477 if (ulDataLen
> EC_MAX_DIGEST_LEN
) {
478 rv
= CKR_DATA_LEN_RANGE
;
482 /* structure assignment */
483 ECkey
.ecParams
= ecc_ctx
->ecparams
;
485 value_len
= EC_MAX_VALUE_LEN
;
486 rv
= soft_get_private_value(key
, CKA_VALUE
, value
, &value_len
);
491 ECkey
.privateValue
.data
= value
;
492 ECkey
.privateValue
.len
= value_len
;
494 signature_item
.data
= pSigned
;
495 signature_item
.len
= *pulSignedLen
;
497 digest_item
.data
= pData
;
498 digest_item
.len
= ulDataLen
;
500 if ((ss
= ECDSA_SignDigest(&ECkey
, &signature_item
, &digest_item
, 0))
502 if (ss
== SECBufferTooSmall
)
503 return (CKR_BUFFER_TOO_SMALL
);
505 rv
= CKR_FUNCTION_FAILED
;
510 *pulSignedLen
= signature_item
.len
;
516 (void) pthread_mutex_lock(&session_p
->session_mutex
);
517 soft_free_ecc_context(session_p
->sign
.context
);
518 session_p
->sign
.context
= NULL
;
519 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
524 soft_ecc_verify(soft_session_t
*session_p
, CK_BYTE_PTR pData
,
525 CK_ULONG ulDataLen
, CK_BYTE_PTR pSignature
,
526 CK_ULONG ulSignatureLen
)
529 soft_ecc_ctx_t
*ecc_ctx
= session_p
->verify
.context
;
530 soft_object_t
*key
= ecc_ctx
->key
;
531 uchar_t point
[EC_MAX_POINT_LEN
];
532 CK_ATTRIBUTE
template;
534 SECItem signature_item
;
537 if ((key
->class != CKO_PUBLIC_KEY
) ||(key
->key_type
!= CKK_EC
)) {
538 rv
= CKR_KEY_TYPE_INCONSISTENT
;
542 if (ulSignatureLen
> EC_MAX_SIG_LEN
) {
543 rv
= CKR_SIGNATURE_LEN_RANGE
;
547 if (ulDataLen
> EC_MAX_DIGEST_LEN
) {
548 rv
= CKR_DATA_LEN_RANGE
;
552 /* structure assignment */
553 ECkey
.ecParams
= ecc_ctx
->ecparams
;
555 template.type
= CKA_EC_POINT
;
556 template.pValue
= point
;
557 template.ulValueLen
= sizeof (point
);
558 rv
= soft_get_public_key_attribute(key
, &template);
563 ECkey
.publicValue
.data
= point
;
564 ECkey
.publicValue
.len
= template.ulValueLen
;
566 signature_item
.data
= pSignature
;
567 signature_item
.len
= ulSignatureLen
;
569 digest_item
.data
= pData
;
570 digest_item
.len
= ulDataLen
;
572 if (ECDSA_VerifyDigest(&ECkey
, &signature_item
, &digest_item
, 0)
574 rv
= CKR_SIGNATURE_INVALID
;
580 (void) pthread_mutex_lock(&session_p
->session_mutex
);
581 soft_free_ecc_context(session_p
->verify
.context
);
582 session_p
->verify
.context
= NULL
;
583 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
589 soft_ecc_digest_verify_common(soft_session_t
*session_p
, CK_BYTE_PTR pData
,
590 CK_ULONG ulDataLen
, CK_BYTE_PTR pSigned
,
591 CK_ULONG ulSignedLen
, boolean_t Final
)
594 CK_BYTE hash
[SHA1_HASH_SIZE
];
595 CK_ULONG hash_len
= SHA1_HASH_SIZE
;
598 rv
= soft_digest_final(session_p
, hash
, &hash_len
);
600 rv
= soft_digest(session_p
, pData
, ulDataLen
, hash
, &hash_len
);
604 (void) pthread_mutex_lock(&session_p
->session_mutex
);
605 soft_free_ecc_context(session_p
->verify
.context
);
606 session_p
->verify
.context
= NULL
;
607 session_p
->digest
.flags
= 0;
608 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
613 * Now, we are ready to verify the data using signature.
614 * soft_ecc_verify() will free the verification key.
616 rv
= soft_ecc_verify(session_p
, hash
, hash_len
,
617 pSigned
, ulSignedLen
);
620 (void) pthread_mutex_lock(&session_p
->session_mutex
);
621 /* soft_digest_common() has freed the digest context */
622 session_p
->digest
.flags
= 0;
623 (void) pthread_mutex_unlock(&session_p
->session_mutex
);