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.
27 #include <cryptoutil.h>
28 #include <security/cryptoki.h>
29 #include <sys/crypto/common.h>
31 #include "softGlobal.h"
32 #include "softSession.h"
34 #include <blowfish_impl.h>
38 #include "softObject.h"
39 #include "softKeystore.h"
40 #include "softKeystoreUtil.h"
43 static CK_MECHANISM_TYPE soft_mechanisms
[] = {
64 CKM_SHA_1_HMAC_GENERAL
,
67 CKM_SHA256_HMAC_GENERAL
,
70 CKM_SHA384_HMAC_GENERAL
,
73 CKM_SHA512_HMAC_GENERAL
,
85 CKM_RSA_PKCS_KEY_PAIR_GEN
,
92 CKM_DH_PKCS_KEY_PAIR_GEN
,
94 CKM_MD5_KEY_DERIVATION
,
95 CKM_SHA1_KEY_DERIVATION
,
96 CKM_SHA256_KEY_DERIVATION
,
97 CKM_SHA384_KEY_DERIVATION
,
98 CKM_SHA512_KEY_DERIVATION
,
101 CKM_SSL3_PRE_MASTER_KEY_GEN
,
102 CKM_TLS_PRE_MASTER_KEY_GEN
,
103 CKM_SSL3_MASTER_KEY_DERIVE
,
104 CKM_TLS_MASTER_KEY_DERIVE
,
105 CKM_SSL3_MASTER_KEY_DERIVE_DH
,
106 CKM_TLS_MASTER_KEY_DERIVE_DH
,
107 CKM_SSL3_KEY_AND_MAC_DERIVE
,
108 CKM_TLS_KEY_AND_MAC_DERIVE
,
117 * This is the table of CK_MECHANISM_INFO structs for the supported mechanisms.
118 * The index for this table is the same as the one above for the same
120 * The minimum and maximum sizes of the key for the mechanism can be measured
121 * in bits or in bytes (i.e. mechanism-dependent). This table specifies the
122 * supported range of key sizes in bytes; unless noted as in bits.
124 static CK_MECHANISM_INFO soft_mechanism_info
[] = {
125 {DES_MINBYTES
, DES_MAXBYTES
,
126 CKF_ENCRYPT
|CKF_DECRYPT
|
127 CKF_WRAP
|CKF_UNWRAP
}, /* CKM_DES_CBC */
128 {DES_MINBYTES
, DES_MAXBYTES
,
129 CKF_ENCRYPT
|CKF_DECRYPT
|
130 CKF_WRAP
|CKF_UNWRAP
}, /* CKM_DES_CBC_PAD */
131 {DES_MINBYTES
, DES_MAXBYTES
,
132 CKF_ENCRYPT
|CKF_DECRYPT
|
133 CKF_WRAP
|CKF_UNWRAP
}, /* CKM_DES_ECB */
134 {DES_MINBYTES
, DES_MAXBYTES
,
135 CKF_GENERATE
}, /* CKM_DES_KEY_GEN */
136 {DES_MINBYTES
, DES_MAXBYTES
,
137 CKF_SIGN
|CKF_VERIFY
}, /* CKM_DES_MAC_GENERAL */
138 {DES_MINBYTES
, DES_MAXBYTES
,
139 CKF_SIGN
|CKF_VERIFY
}, /* CKM_DES_MAC */
140 {DES3_MINBYTES
, DES3_MAXBYTES
,
141 CKF_ENCRYPT
|CKF_DECRYPT
|
142 CKF_WRAP
|CKF_UNWRAP
}, /* CKM_DES3_CBC */
143 {DES3_MINBYTES
, DES3_MAXBYTES
,
144 CKF_ENCRYPT
|CKF_DECRYPT
|
145 CKF_WRAP
|CKF_UNWRAP
}, /* CKM_DES3_CBC_PAD */
146 {DES3_MINBYTES
, DES3_MAXBYTES
,
147 CKF_ENCRYPT
|CKF_DECRYPT
|
148 CKF_WRAP
|CKF_UNWRAP
}, /* CKM_DES3_ECB */
149 {DES2_MAXBYTES
, DES2_MAXBYTES
,
150 CKF_GENERATE
}, /* CKM_DES2_KEY_GEN */
151 {DES3_MAXBYTES
, DES3_MAXBYTES
, /* CKK_DES3 only */
152 CKF_GENERATE
}, /* CKM_DES3_KEY_GEN */
153 {AES_MINBYTES
, AES_MAXBYTES
,
154 CKF_ENCRYPT
|CKF_DECRYPT
|
155 CKF_WRAP
|CKF_UNWRAP
}, /* CKM_AES_CBC */
156 {AES_MINBYTES
, AES_MAXBYTES
,
157 CKF_ENCRYPT
|CKF_DECRYPT
|
158 CKF_WRAP
|CKF_UNWRAP
}, /* CKM_AES_CBC_PAD */
159 {AES_MINBYTES
, AES_MAXBYTES
,
160 CKF_ENCRYPT
|CKF_DECRYPT
|
161 CKF_WRAP
|CKF_UNWRAP
}, /* CKM_AES_CTR */
162 {AES_MINBYTES
, AES_MAXBYTES
,
163 CKF_ENCRYPT
|CKF_DECRYPT
|
164 CKF_WRAP
|CKF_UNWRAP
}, /* CKM_AES_ECB */
165 {AES_MINBYTES
, AES_MAXBYTES
,
166 CKF_GENERATE
}, /* CKM_AES_KEY_GEN */
167 {BLOWFISH_MINBYTES
, BLOWFISH_MAXBYTES
,
168 CKF_ENCRYPT
|CKF_DECRYPT
|
169 CKF_WRAP
|CKF_UNWRAP
}, /* CKM_BLOWFISH_ECB */
170 {BLOWFISH_MINBYTES
, BLOWFISH_MAXBYTES
,
171 CKF_GENERATE
}, /* CKM_BLOWFISH_KEY_GEN */
172 {0, 0, CKF_DIGEST
}, /* CKM_SHA_1 */
173 {1, 64, CKF_SIGN
|CKF_VERIFY
}, /* CKM_SHA_1_HMAC */
174 {1, 64, CKF_SIGN
|CKF_VERIFY
}, /* CKM_SHA_1_HMAC_GENERAL */
175 {0, 0, CKF_DIGEST
}, /* CKM_SHA256 */
176 {1, 64, CKF_SIGN
|CKF_VERIFY
}, /* CKM_SHA256_HMAC */
177 {1, 64, CKF_SIGN
|CKF_VERIFY
}, /* CKM_SHA256_HMAC_GENERAL */
178 {0, 0, CKF_DIGEST
}, /* CKM_SHA384 */
179 {1, 128, CKF_SIGN
|CKF_VERIFY
}, /* CKM_SHA384_HMAC */
180 {1, 128, CKF_SIGN
|CKF_VERIFY
}, /* CKM_SHA384_HMAC_GENERAL */
181 {0, 0, CKF_DIGEST
}, /* CKM_SHA512 */
182 {1, 128, CKF_SIGN
|CKF_VERIFY
}, /* CKM_SHA512_HMAC */
183 {1, 128, CKF_SIGN
|CKF_VERIFY
}, /* CKM_SHA512_HMAC_GENERAL */
184 {1, 512, CKF_SIGN
|CKF_VERIFY
}, /* CKM_SSL3_SHA1_MAC */
185 {0, 0, CKF_DIGEST
}, /* CKM_MD5 */
186 {1, 64, CKF_SIGN
|CKF_VERIFY
}, /* CKM_MD5_HMAC */
187 {1, 64, CKF_SIGN
|CKF_VERIFY
}, /* CKM_MD5_HMAC_GENERAL */
188 {1, 512, CKF_SIGN
|CKF_VERIFY
}, /* CKM_SSL3_MD5_MAC */
189 {8, ARCFOUR_MAX_KEY_BITS
, CKF_ENCRYPT
|CKF_DECRYPT
}, /* CKM_RC4; */
191 {8, ARCFOUR_MAX_KEY_BITS
, CKF_GENERATE
}, /* CKM_RC4_KEY_GEN; in bits */
192 {512, 1024, CKF_SIGN
|CKF_VERIFY
}, /* CKM_DSA; in bits */
193 {512, 1024, CKF_SIGN
|CKF_VERIFY
}, /* CKM_DSA_SHA1; in bits */
194 {512, 1024, CKF_GENERATE_KEY_PAIR
}, /* CKM_DSA_KEY_PAIR_GEN; */
196 {256, 4096, CKF_ENCRYPT
|CKF_DECRYPT
|
197 CKF_SIGN
|CKF_SIGN_RECOVER
|
199 CKF_VERIFY
|CKF_VERIFY_RECOVER
}, /* CKM_RSA_PKCS; in bits */
200 {256, 4096, CKF_GENERATE_KEY_PAIR
}, /* CKM_RSA_PKCS_KEY_PAIR_GEN; */
202 {256, 4096, CKF_ENCRYPT
|CKF_DECRYPT
|
203 CKF_SIGN
|CKF_SIGN_RECOVER
|
205 CKF_VERIFY
|CKF_VERIFY_RECOVER
}, /* CKM_RSA_X_509 in bits */
206 {256, 4096, CKF_SIGN
|CKF_VERIFY
}, /* CKM_MD5_RSA_PKCS in bits */
207 {256, 4096, CKF_SIGN
|CKF_VERIFY
}, /* CKM_SHA1_RSA_PKCS in bits */
208 {256, 4096, CKF_SIGN
|CKF_VERIFY
}, /* CKM_SHA256_RSA_PKCS in bits */
209 {256, 4096, CKF_SIGN
|CKF_VERIFY
}, /* CKM_SHA384_RSA_PKCS in bits */
210 {256, 4096, CKF_SIGN
|CKF_VERIFY
}, /* CKM_SHA512_RSA_PKCS in bits */
211 {DH_MIN_KEY_LEN
, DH_MAX_KEY_LEN
, CKF_GENERATE_KEY_PAIR
},
212 /* CKM_DH_PKCS_KEY_PAIR_GEN */
214 {DH_MIN_KEY_LEN
, DH_MAX_KEY_LEN
, CKF_DERIVE
},
215 /* CKM_DH_PKCS_DERIVE; */
217 {1, 16, CKF_DERIVE
}, /* CKM_MD5_KEY_DERIVATION */
218 {1, 20, CKF_DERIVE
}, /* CKM_SHA1_KEY_DERIVATION */
219 {1, 32, CKF_DERIVE
}, /* CKM_SHA256_KEY_DERIVATION */
220 {1, 48, CKF_DERIVE
}, /* CKM_SHA384_KEY_DERIVATION */
221 {1, 64, CKF_DERIVE
}, /* CKM_SHA512_KEY_DERIVATION */
222 {0, 0, CKF_GENERATE
}, /* CKM_PBE_SHA1_RC4_128 */
223 {0, 0, CKF_GENERATE
}, /* CKM_PKCS5_PBKD2 */
224 {48, 48, CKF_GENERATE
}, /* CKM_SSL3_PRE_MASTER_KEY_GEN */
225 {48, 48, CKF_GENERATE
}, /* CKM_TLS_PRE_MASTER_KEY_GEN */
226 {48, 48, CKF_DERIVE
}, /* CKM_SSL3_MASTER_KEY_DERIVE */
227 {48, 48, CKF_DERIVE
}, /* CKM_TLS_MASTER_KEY_DERIVE */
228 {48, 48, CKF_DERIVE
}, /* CKM_SSL3_MASTER_KEY_DERIVE_DH */
229 {48, 48, CKF_DERIVE
}, /* CKM_TLS_MASTER_KEY_DERIVE_DH */
230 {0, 0, CKF_DERIVE
}, /* CKM_SSL3_KEY_AND_MAC_DERIVE */
231 {0, 0, CKF_DERIVE
}, /* CKM_TLS_KEY_AND_MAC_DERIVE */
232 {0, 0, CKF_DERIVE
}, /* CKM_TLS_PRF */
233 {EC_MIN_KEY_LEN
, EC_MAX_KEY_LEN
, CKF_GENERATE_KEY_PAIR
},
234 {EC_MIN_KEY_LEN
, EC_MAX_KEY_LEN
, CKF_SIGN
|CKF_VERIFY
},
235 {EC_MIN_KEY_LEN
, EC_MAX_KEY_LEN
, CKF_SIGN
|CKF_VERIFY
},
236 {EC_MIN_KEY_LEN
, EC_MAX_KEY_LEN
, CKF_DERIVE
}
240 * Slot ID for softtoken is always 1. tokenPresent is ignored.
241 * Also, only one slot is used.
245 C_GetSlotList(CK_BBOOL tokenPresent
, CK_SLOT_ID_PTR pSlotList
,
246 CK_ULONG_PTR pulCount
)
251 if (!softtoken_initialized
)
252 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
254 if (pulCount
== NULL
) {
255 return (CKR_ARGUMENTS_BAD
);
258 if (pSlotList
== NULL
) {
260 * Application only wants to know the number of slots.
266 if ((*pulCount
< 1) && (pSlotList
!= NULL
)) {
267 rv
= CKR_BUFFER_TOO_SMALL
;
269 pSlotList
[0] = SOFTTOKEN_SLOTID
;
279 C_GetSlotInfo(CK_SLOT_ID slotID
, CK_SLOT_INFO_PTR pInfo
)
282 if (!softtoken_initialized
)
283 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
286 return (CKR_ARGUMENTS_BAD
);
288 /* Make sure the slot ID is valid */
289 if (slotID
!= SOFTTOKEN_SLOTID
)
290 return (CKR_SLOT_ID_INVALID
);
292 /* Provide information about the slot in the provided buffer */
293 (void) strncpy((char *)pInfo
->slotDescription
, SOFT_SLOT_DESCRIPTION
,
295 (void) strncpy((char *)pInfo
->manufacturerID
, SOFT_MANUFACTURER_ID
, 32);
296 pInfo
->flags
= CKF_TOKEN_PRESENT
;
297 pInfo
->hardwareVersion
.major
= HARDWARE_VERSION_MAJOR
;
298 pInfo
->hardwareVersion
.minor
= HARDWARE_VERSION_MINOR
;
299 pInfo
->firmwareVersion
.major
= FIRMWARE_VERSION_MAJOR
;
300 pInfo
->firmwareVersion
.minor
= FIRMWARE_VERSION_MINOR
;
306 C_GetTokenInfo(CK_SLOT_ID slotID
, CK_TOKEN_INFO_PTR pInfo
)
308 boolean_t pin_initialized
= B_FALSE
;
309 char *ks_cryptpin
= NULL
;
311 if (!softtoken_initialized
)
312 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
314 /* Make sure the slot ID is valid */
315 if (slotID
!= SOFTTOKEN_SLOTID
)
316 return (CKR_SLOT_ID_INVALID
);
319 return (CKR_ARGUMENTS_BAD
);
322 * It is intentional that we don't forward the error code
323 * returned from soft_keystore_pin_initialized() to the caller
325 pInfo
->flags
= SOFT_TOKEN_FLAGS
;
326 if (soft_slot
.keystore_load_status
== KEYSTORE_UNAVAILABLE
) {
327 pInfo
->flags
|= CKF_WRITE_PROTECTED
;
329 if ((soft_keystore_pin_initialized(&pin_initialized
,
330 &ks_cryptpin
, B_FALSE
) == CKR_OK
) && !pin_initialized
)
331 pInfo
->flags
|= CKF_USER_PIN_TO_BE_CHANGED
;
336 /* Provide information about a token in the provided buffer */
337 (void) strncpy((char *)pInfo
->label
, SOFT_TOKEN_LABEL
, 32);
338 (void) strncpy((char *)pInfo
->manufacturerID
, SOFT_MANUFACTURER_ID
, 32);
339 (void) strncpy((char *)pInfo
->model
, TOKEN_MODEL
, 16);
340 (void) strncpy((char *)pInfo
->serialNumber
, SOFT_TOKEN_SERIAL
, 16);
342 pInfo
->ulMaxSessionCount
= CK_EFFECTIVELY_INFINITE
;
343 pInfo
->ulSessionCount
= soft_session_cnt
;
344 pInfo
->ulMaxRwSessionCount
= CK_EFFECTIVELY_INFINITE
;
345 pInfo
->ulRwSessionCount
= soft_session_rw_cnt
;
346 pInfo
->ulMaxPinLen
= MAX_PIN_LEN
;
347 pInfo
->ulMinPinLen
= MIN_PIN_LEN
;
348 pInfo
->ulTotalPublicMemory
= CK_UNAVAILABLE_INFORMATION
;
349 pInfo
->ulFreePublicMemory
= CK_UNAVAILABLE_INFORMATION
;
350 pInfo
->ulTotalPrivateMemory
= CK_UNAVAILABLE_INFORMATION
;
351 pInfo
->ulFreePrivateMemory
= CK_UNAVAILABLE_INFORMATION
;
352 pInfo
->hardwareVersion
.major
= HARDWARE_VERSION_MAJOR
;
353 pInfo
->hardwareVersion
.minor
= HARDWARE_VERSION_MINOR
;
354 pInfo
->firmwareVersion
.major
= FIRMWARE_VERSION_MAJOR
;
355 pInfo
->firmwareVersion
.minor
= FIRMWARE_VERSION_MINOR
;
356 (void) memset(pInfo
->utcTime
, ' ', 16);
363 C_WaitForSlotEvent(CK_FLAGS flags
, CK_SLOT_ID_PTR pSlot
, CK_VOID_PTR pReserved
)
365 if (!softtoken_initialized
)
366 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
369 * This is currently not implemented, however we could cause this
370 * to wait for the token files to appear if soft_token_present is
372 * However there is currently no polite and portable way to do that
373 * because we might not even be able to get to an fd to the
374 * parent directory, so instead we don't support any slot events.
376 return (CKR_FUNCTION_NOT_SUPPORTED
);
381 C_GetMechanismList(CK_SLOT_ID slotID
, CK_MECHANISM_TYPE_PTR pMechanismList
,
382 CK_ULONG_PTR pulCount
)
388 if (!softtoken_initialized
)
389 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
391 if (slotID
!= SOFTTOKEN_SLOTID
)
392 return (CKR_SLOT_ID_INVALID
);
394 mechnum
= sizeof (soft_mechanisms
) / sizeof (CK_MECHANISM_TYPE
);
396 if (pMechanismList
== NULL
) {
398 * Application only wants to know the number of
399 * supported mechanism types.
405 if (*pulCount
< mechnum
) {
407 return (CKR_BUFFER_TOO_SMALL
);
410 for (i
= 0; i
< mechnum
; i
++) {
411 pMechanismList
[i
] = soft_mechanisms
[i
];
421 C_GetMechanismInfo(CK_SLOT_ID slotID
, CK_MECHANISM_TYPE type
,
422 CK_MECHANISM_INFO_PTR pInfo
)
428 if (!softtoken_initialized
)
429 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
431 if (slotID
!= SOFTTOKEN_SLOTID
)
432 return (CKR_SLOT_ID_INVALID
);
435 return (CKR_ARGUMENTS_BAD
);
438 mechnum
= sizeof (soft_mechanisms
) / sizeof (CK_MECHANISM_TYPE
);
439 for (i
= 0; i
< mechnum
; i
++) {
440 if (soft_mechanisms
[i
] == type
)
445 /* unsupported mechanism */
446 return (CKR_MECHANISM_INVALID
);
448 pInfo
->ulMinKeySize
= soft_mechanism_info
[i
].ulMinKeySize
;
449 pInfo
->ulMaxKeySize
= soft_mechanism_info
[i
].ulMaxKeySize
;
450 pInfo
->flags
= soft_mechanism_info
[i
].flags
;
458 C_InitToken(CK_SLOT_ID slotID
, CK_UTF8CHAR_PTR pPin
, CK_ULONG ulPinLen
,
459 CK_UTF8CHAR_PTR pLabel
)
461 if (!softtoken_initialized
)
462 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
464 if (create_keystore() != 0)
465 return (CKR_FUNCTION_FAILED
);
472 C_InitPIN(CK_SESSION_HANDLE hSession
, CK_UTF8CHAR_PTR pPin
, CK_ULONG ulPinLen
)
474 if (!softtoken_initialized
)
475 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
477 return (CKR_FUNCTION_NOT_SUPPORTED
);
482 C_SetPIN(CK_SESSION_HANDLE hSession
, CK_UTF8CHAR_PTR pOldPin
,
483 CK_ULONG ulOldPinLen
, CK_UTF8CHAR_PTR pNewPin
, CK_ULONG ulNewPinLen
)
486 soft_session_t
*session_p
;
488 boolean_t lock_held
= B_FALSE
;
490 if (!softtoken_initialized
)
491 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
494 * Obtain the session pointer. Also, increment the session
497 rv
= handle2session(hSession
, &session_p
);
501 if (!soft_keystore_status(KEYSTORE_LOAD
)) {
502 SES_REFRELE(session_p
, lock_held
);
503 return (CKR_DEVICE_REMOVED
);
506 if ((ulOldPinLen
< MIN_PIN_LEN
) || (ulOldPinLen
> MAX_PIN_LEN
) ||
507 (ulNewPinLen
< MIN_PIN_LEN
) ||(ulNewPinLen
> MAX_PIN_LEN
)) {
508 SES_REFRELE(session_p
, lock_held
);
509 return (CKR_PIN_LEN_RANGE
);
512 if ((pOldPin
== NULL_PTR
) || (pNewPin
== NULL_PTR
)) {
514 * We don't support CKF_PROTECTED_AUTHENTICATION_PATH
516 SES_REFRELE(session_p
, lock_held
);
517 return (CKR_ARGUMENTS_BAD
);
520 /* check the state of the session */
521 if ((session_p
->state
!= CKS_RW_PUBLIC_SESSION
) &&
522 (session_p
->state
!= CKS_RW_USER_FUNCTIONS
)) {
523 SES_REFRELE(session_p
, lock_held
);
524 return (CKR_SESSION_READ_ONLY
);
527 rv
= soft_setpin(pOldPin
, ulOldPinLen
, pNewPin
, ulNewPinLen
);
529 SES_REFRELE(session_p
, lock_held
);