00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef PKCS11CRYPTO
00020
00021 #include <config.h>
00022
00023 #include <string.h>
00024
00025 #include <isc/entropy.h>
00026 #include <isc/mem.h>
00027 #include <isc/sha1.h>
00028 #include <isc/util.h>
00029
00030 #include <dst/result.h>
00031
00032 #include "dst_internal.h"
00033 #include "dst_parse.h"
00034 #include "dst_pkcs11.h"
00035
00036 #include <pk11/internal.h>
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 #define CKA_VALUE2 CKA_PRIVATE_EXPONENT
00069
00070 #define DST_RET(a) {ret = a; goto err;}
00071
00072 static CK_BBOOL truevalue = TRUE;
00073 static CK_BBOOL falsevalue = FALSE;
00074
00075 static isc_result_t pkcs11dsa_todns(const dst_key_t *key, isc_buffer_t *data);
00076 static void pkcs11dsa_destroy(dst_key_t *key);
00077
00078 static isc_result_t
00079 pkcs11dsa_createctx_sign(dst_key_t *key, dst_context_t *dctx) {
00080 CK_RV rv;
00081 CK_MECHANISM mech = { CKM_DSA_SHA1, NULL, 0 };
00082 CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
00083 CK_KEY_TYPE keyType = CKK_DSA;
00084 CK_ATTRIBUTE keyTemplate[] =
00085 {
00086 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
00087 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
00088 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00089 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00090 { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00091 { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
00092 { CKA_PRIME, NULL, 0 },
00093 { CKA_SUBPRIME, NULL, 0 },
00094 { CKA_BASE, NULL, 0 },
00095 { CKA_VALUE, NULL, 0 }
00096 };
00097 CK_ATTRIBUTE *attr;
00098 pk11_object_t *dsa;
00099 pk11_context_t *pk11_ctx;
00100 isc_result_t ret;
00101 unsigned int i;
00102
00103 pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx,
00104 sizeof(*pk11_ctx));
00105 if (pk11_ctx == NULL)
00106 return (ISC_R_NOMEMORY);
00107 ret = pk11_get_session(pk11_ctx, OP_DSA, ISC_TRUE, ISC_FALSE,
00108 ISC_FALSE, NULL, pk11_get_best_token(OP_DSA));
00109 if (ret != ISC_R_SUCCESS)
00110 goto err;
00111
00112 dsa = key->keydata.pkey;
00113 if (dsa->ontoken && (dsa->object != CK_INVALID_HANDLE)) {
00114 pk11_ctx->ontoken = dsa->ontoken;
00115 pk11_ctx->object = dsa->object;
00116 goto token_key;
00117 }
00118
00119 for (attr = pk11_attribute_first(dsa);
00120 attr != NULL;
00121 attr = pk11_attribute_next(dsa, attr))
00122 switch (attr->type) {
00123 case CKA_PRIME:
00124 INSIST(keyTemplate[6].type == attr->type);
00125 keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
00126 attr->ulValueLen);
00127 if (keyTemplate[6].pValue == NULL)
00128 DST_RET(ISC_R_NOMEMORY);
00129 memmove(keyTemplate[6].pValue, attr->pValue,
00130 attr->ulValueLen);
00131 keyTemplate[6].ulValueLen = attr->ulValueLen;
00132 break;
00133 case CKA_SUBPRIME:
00134 INSIST(keyTemplate[7].type == attr->type);
00135 keyTemplate[7].pValue = isc_mem_get(dctx->mctx,
00136 attr->ulValueLen);
00137 if (keyTemplate[7].pValue == NULL)
00138 DST_RET(ISC_R_NOMEMORY);
00139 memmove(keyTemplate[7].pValue, attr->pValue,
00140 attr->ulValueLen);
00141 keyTemplate[7].ulValueLen = attr->ulValueLen;
00142 break;
00143 case CKA_BASE:
00144 INSIST(keyTemplate[8].type == attr->type);
00145 keyTemplate[8].pValue = isc_mem_get(dctx->mctx,
00146 attr->ulValueLen);
00147 if (keyTemplate[8].pValue == NULL)
00148 DST_RET(ISC_R_NOMEMORY);
00149 memmove(keyTemplate[8].pValue, attr->pValue,
00150 attr->ulValueLen);
00151 keyTemplate[8].ulValueLen = attr->ulValueLen;
00152 break;
00153 case CKA_VALUE2:
00154 INSIST(keyTemplate[9].type == CKA_VALUE);
00155 keyTemplate[9].pValue = isc_mem_get(dctx->mctx,
00156 attr->ulValueLen);
00157 if (keyTemplate[9].pValue == NULL)
00158 DST_RET(ISC_R_NOMEMORY);
00159 memmove(keyTemplate[9].pValue, attr->pValue,
00160 attr->ulValueLen);
00161 keyTemplate[9].ulValueLen = attr->ulValueLen;
00162 break;
00163 }
00164 pk11_ctx->object = CK_INVALID_HANDLE;
00165 pk11_ctx->ontoken = ISC_FALSE;
00166 PK11_RET(pkcs_C_CreateObject,
00167 (pk11_ctx->session,
00168 keyTemplate, (CK_ULONG) 10,
00169 &pk11_ctx->object),
00170 ISC_R_FAILURE);
00171
00172 token_key:
00173
00174 PK11_RET(pkcs_C_SignInit,
00175 (pk11_ctx->session, &mech, pk11_ctx->object),
00176 ISC_R_FAILURE);
00177
00178 dctx->ctxdata.pk11_ctx = pk11_ctx;
00179
00180 for (i = 6; i <= 9; i++)
00181 if (keyTemplate[i].pValue != NULL) {
00182 memset(keyTemplate[i].pValue, 0,
00183 keyTemplate[i].ulValueLen);
00184 isc_mem_put(dctx->mctx,
00185 keyTemplate[i].pValue,
00186 keyTemplate[i].ulValueLen);
00187 }
00188
00189 return (ISC_R_SUCCESS);
00190
00191 err:
00192 if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE))
00193 (void) pkcs_C_DestroyObject(pk11_ctx->session, pk11_ctx->object);
00194 for (i = 6; i <= 9; i++)
00195 if (keyTemplate[i].pValue != NULL) {
00196 memset(keyTemplate[i].pValue, 0,
00197 keyTemplate[i].ulValueLen);
00198 isc_mem_put(dctx->mctx,
00199 keyTemplate[i].pValue,
00200 keyTemplate[i].ulValueLen);
00201 }
00202 pk11_return_session(pk11_ctx);
00203 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00204 isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
00205
00206 return (ret);
00207 }
00208
00209 static isc_result_t
00210 pkcs11dsa_createctx_verify(dst_key_t *key, dst_context_t *dctx) {
00211 CK_RV rv;
00212 CK_MECHANISM mech = { CKM_DSA_SHA1, NULL, 0 };
00213 CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
00214 CK_KEY_TYPE keyType = CKK_DSA;
00215 CK_ATTRIBUTE keyTemplate[] =
00216 {
00217 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
00218 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
00219 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00220 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00221 { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
00222 { CKA_PRIME, NULL, 0 },
00223 { CKA_SUBPRIME, NULL, 0 },
00224 { CKA_BASE, NULL, 0 },
00225 { CKA_VALUE, NULL, 0 }
00226 };
00227 CK_ATTRIBUTE *attr;
00228 pk11_object_t *dsa;
00229 pk11_context_t *pk11_ctx;
00230 isc_result_t ret;
00231 unsigned int i;
00232
00233 pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx,
00234 sizeof(*pk11_ctx));
00235 if (pk11_ctx == NULL)
00236 return (ISC_R_NOMEMORY);
00237 ret = pk11_get_session(pk11_ctx, OP_DSA, ISC_TRUE, ISC_FALSE,
00238 ISC_FALSE, NULL, pk11_get_best_token(OP_DSA));
00239 if (ret != ISC_R_SUCCESS)
00240 goto err;
00241
00242 dsa = key->keydata.pkey;
00243 if (dsa->ontoken && (dsa->object != CK_INVALID_HANDLE)) {
00244 pk11_ctx->ontoken = dsa->ontoken;
00245 pk11_ctx->object = dsa->object;
00246 goto token_key;
00247 }
00248
00249 for (attr = pk11_attribute_first(dsa);
00250 attr != NULL;
00251 attr = pk11_attribute_next(dsa, attr))
00252 switch (attr->type) {
00253 case CKA_PRIME:
00254 INSIST(keyTemplate[5].type == attr->type);
00255 keyTemplate[5].pValue = isc_mem_get(dctx->mctx,
00256 attr->ulValueLen);
00257 if (keyTemplate[5].pValue == NULL)
00258 DST_RET(ISC_R_NOMEMORY);
00259 memmove(keyTemplate[5].pValue, attr->pValue,
00260 attr->ulValueLen);
00261 keyTemplate[5].ulValueLen = attr->ulValueLen;
00262 break;
00263 case CKA_SUBPRIME:
00264 INSIST(keyTemplate[6].type == attr->type);
00265 keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
00266 attr->ulValueLen);
00267 if (keyTemplate[6].pValue == NULL)
00268 DST_RET(ISC_R_NOMEMORY);
00269 memmove(keyTemplate[6].pValue, attr->pValue,
00270 attr->ulValueLen);
00271 keyTemplate[6].ulValueLen = attr->ulValueLen;
00272 break;
00273 case CKA_BASE:
00274 INSIST(keyTemplate[7].type == attr->type);
00275 keyTemplate[7].pValue = isc_mem_get(dctx->mctx,
00276 attr->ulValueLen);
00277 if (keyTemplate[7].pValue == NULL)
00278 DST_RET(ISC_R_NOMEMORY);
00279 memmove(keyTemplate[7].pValue, attr->pValue,
00280 attr->ulValueLen);
00281 keyTemplate[7].ulValueLen = attr->ulValueLen;
00282 break;
00283 case CKA_VALUE:
00284 INSIST(keyTemplate[8].type == attr->type);
00285 keyTemplate[8].pValue = isc_mem_get(dctx->mctx,
00286 attr->ulValueLen);
00287 if (keyTemplate[8].pValue == NULL)
00288 DST_RET(ISC_R_NOMEMORY);
00289 memmove(keyTemplate[8].pValue, attr->pValue,
00290 attr->ulValueLen);
00291 keyTemplate[8].ulValueLen = attr->ulValueLen;
00292 break;
00293 }
00294 pk11_ctx->object = CK_INVALID_HANDLE;
00295 pk11_ctx->ontoken = ISC_FALSE;
00296 PK11_RET(pkcs_C_CreateObject,
00297 (pk11_ctx->session,
00298 keyTemplate, (CK_ULONG) 9,
00299 &pk11_ctx->object),
00300 ISC_R_FAILURE);
00301
00302 token_key:
00303
00304 PK11_RET(pkcs_C_VerifyInit,
00305 (pk11_ctx->session, &mech, pk11_ctx->object),
00306 ISC_R_FAILURE);
00307
00308 dctx->ctxdata.pk11_ctx = pk11_ctx;
00309
00310 for (i = 5; i <= 8; i++)
00311 if (keyTemplate[i].pValue != NULL) {
00312 memset(keyTemplate[i].pValue, 0,
00313 keyTemplate[i].ulValueLen);
00314 isc_mem_put(dctx->mctx,
00315 keyTemplate[i].pValue,
00316 keyTemplate[i].ulValueLen);
00317 }
00318
00319 return (ISC_R_SUCCESS);
00320
00321 err:
00322 if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE))
00323 (void) pkcs_C_DestroyObject(pk11_ctx->session, pk11_ctx->object);
00324 for (i = 5; i <= 8; i++)
00325 if (keyTemplate[i].pValue != NULL) {
00326 memset(keyTemplate[i].pValue, 0,
00327 keyTemplate[i].ulValueLen);
00328 isc_mem_put(dctx->mctx,
00329 keyTemplate[i].pValue,
00330 keyTemplate[i].ulValueLen);
00331 }
00332 pk11_return_session(pk11_ctx);
00333 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00334 isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
00335
00336 return (ret);
00337 }
00338
00339 static isc_result_t
00340 pkcs11dsa_createctx(dst_key_t *key, dst_context_t *dctx) {
00341 if (dctx->use == DO_SIGN)
00342 return (pkcs11dsa_createctx_sign(key, dctx));
00343 else
00344 return (pkcs11dsa_createctx_verify(key, dctx));
00345 }
00346
00347 static void
00348 pkcs11dsa_destroyctx(dst_context_t *dctx) {
00349 pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
00350
00351 if (pk11_ctx != NULL) {
00352 if (!pk11_ctx->ontoken &&
00353 (pk11_ctx->object != CK_INVALID_HANDLE))
00354 (void) pkcs_C_DestroyObject(pk11_ctx->session,
00355 pk11_ctx->object);
00356 pk11_return_session(pk11_ctx);
00357 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00358 isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
00359 dctx->ctxdata.pk11_ctx = NULL;
00360 }
00361 }
00362
00363 static isc_result_t
00364 pkcs11dsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
00365 CK_RV rv;
00366 pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
00367 isc_result_t ret = ISC_R_SUCCESS;
00368
00369 if (dctx->use == DO_SIGN)
00370 PK11_CALL(pkcs_C_SignUpdate,
00371 (pk11_ctx->session,
00372 (CK_BYTE_PTR) data->base,
00373 (CK_ULONG) data->length),
00374 ISC_R_FAILURE);
00375 else
00376 PK11_CALL(pkcs_C_VerifyUpdate,
00377 (pk11_ctx->session,
00378 (CK_BYTE_PTR) data->base,
00379 (CK_ULONG) data->length),
00380 ISC_R_FAILURE);
00381 return (ret);
00382 }
00383
00384 static isc_result_t
00385 pkcs11dsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
00386 CK_RV rv;
00387 CK_ULONG siglen = ISC_SHA1_DIGESTLENGTH * 2;
00388 isc_region_t r;
00389 pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
00390 isc_result_t ret = ISC_R_SUCCESS;
00391
00392 isc_buffer_availableregion(sig, &r);
00393 if (r.length < ISC_SHA1_DIGESTLENGTH * 2 + 1)
00394 return (ISC_R_NOSPACE);
00395
00396 PK11_RET(pkcs_C_SignFinal,
00397 (pk11_ctx->session, (CK_BYTE_PTR) r.base + 1, &siglen),
00398 DST_R_SIGNFAILURE);
00399 if (siglen != ISC_SHA1_DIGESTLENGTH * 2)
00400 return (DST_R_SIGNFAILURE);
00401
00402 *r.base = (dctx->key->key_size - 512)/64;
00403 isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH * 2 + 1);
00404
00405 err:
00406 return (ret);
00407 }
00408
00409 static isc_result_t
00410 pkcs11dsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
00411 CK_RV rv;
00412 pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
00413 isc_result_t ret = ISC_R_SUCCESS;
00414
00415 PK11_CALL(pkcs_C_VerifyFinal,
00416 (pk11_ctx->session,
00417 (CK_BYTE_PTR) sig->base + 1,
00418 (CK_ULONG) sig->length - 1),
00419 DST_R_VERIFYFAILURE);
00420 return (ret);
00421 }
00422
00423 static isc_boolean_t
00424 pkcs11dsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
00425 pk11_object_t *dsa1, *dsa2;
00426 CK_ATTRIBUTE *attr1, *attr2;
00427
00428 dsa1 = key1->keydata.pkey;
00429 dsa2 = key2->keydata.pkey;
00430
00431 if ((dsa1 == NULL) && (dsa2 == NULL))
00432 return (ISC_TRUE);
00433 else if ((dsa1 == NULL) || (dsa2 == NULL))
00434 return (ISC_FALSE);
00435
00436 attr1 = pk11_attribute_bytype(dsa1, CKA_PRIME);
00437 attr2 = pk11_attribute_bytype(dsa2, CKA_PRIME);
00438 if ((attr1 == NULL) && (attr2 == NULL))
00439 return (ISC_TRUE);
00440 else if ((attr1 == NULL) || (attr2 == NULL) ||
00441 (attr1->ulValueLen != attr2->ulValueLen) ||
00442 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
00443 return (ISC_FALSE);
00444
00445 attr1 = pk11_attribute_bytype(dsa1, CKA_SUBPRIME);
00446 attr2 = pk11_attribute_bytype(dsa2, CKA_SUBPRIME);
00447 if ((attr1 == NULL) && (attr2 == NULL))
00448 return (ISC_TRUE);
00449 else if ((attr1 == NULL) || (attr2 == NULL) ||
00450 (attr1->ulValueLen != attr2->ulValueLen) ||
00451 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
00452 return (ISC_FALSE);
00453
00454 attr1 = pk11_attribute_bytype(dsa1, CKA_BASE);
00455 attr2 = pk11_attribute_bytype(dsa2, CKA_BASE);
00456 if ((attr1 == NULL) && (attr2 == NULL))
00457 return (ISC_TRUE);
00458 else if ((attr1 == NULL) || (attr2 == NULL) ||
00459 (attr1->ulValueLen != attr2->ulValueLen) ||
00460 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
00461 return (ISC_FALSE);
00462
00463 attr1 = pk11_attribute_bytype(dsa1, CKA_VALUE);
00464 attr2 = pk11_attribute_bytype(dsa2, CKA_VALUE);
00465 if ((attr1 == NULL) && (attr2 == NULL))
00466 return (ISC_TRUE);
00467 else if ((attr1 == NULL) || (attr2 == NULL) ||
00468 (attr1->ulValueLen != attr2->ulValueLen) ||
00469 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
00470 return (ISC_FALSE);
00471
00472 attr1 = pk11_attribute_bytype(dsa1, CKA_VALUE2);
00473 attr2 = pk11_attribute_bytype(dsa2, CKA_VALUE2);
00474 if (((attr1 != NULL) || (attr2 != NULL)) &&
00475 ((attr1 == NULL) || (attr2 == NULL) ||
00476 (attr1->ulValueLen != attr2->ulValueLen) ||
00477 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)))
00478 return (ISC_FALSE);
00479
00480 if (!dsa1->ontoken && !dsa2->ontoken)
00481 return (ISC_TRUE);
00482 else if (dsa1->ontoken || dsa2->ontoken ||
00483 (dsa1->object != dsa2->object))
00484 return (ISC_FALSE);
00485
00486 return (ISC_TRUE);
00487 }
00488
00489 static isc_result_t
00490 pkcs11dsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
00491 CK_RV rv;
00492 CK_MECHANISM mech = { CKM_DSA_PARAMETER_GEN, NULL, 0 };
00493 CK_OBJECT_HANDLE dp = CK_INVALID_HANDLE;
00494 CK_OBJECT_CLASS dpClass = CKO_DOMAIN_PARAMETERS;
00495 CK_KEY_TYPE keyType = CKK_DSA;
00496 CK_ULONG bits = 0;
00497 CK_ATTRIBUTE dpTemplate[] =
00498 {
00499 { CKA_CLASS, &dpClass, (CK_ULONG) sizeof(dpClass) },
00500 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
00501 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00502 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00503 { CKA_PRIME_BITS, &bits, (CK_ULONG) sizeof(bits) },
00504 };
00505 CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE;
00506 CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
00507 CK_ATTRIBUTE pubTemplate[] =
00508 {
00509 { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) },
00510 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
00511 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00512 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00513 { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
00514 { CKA_PRIME, NULL, 0 },
00515 { CKA_SUBPRIME, NULL, 0 },
00516 { CKA_BASE, NULL, 0 }
00517 };
00518 CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE;
00519 CK_OBJECT_HANDLE privClass = CKO_PRIVATE_KEY;
00520 CK_ATTRIBUTE privTemplate[] =
00521 {
00522 { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) },
00523 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
00524 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00525 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00526 { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00527 { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) },
00528 { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
00529 };
00530 CK_ATTRIBUTE *attr;
00531 pk11_object_t *dsa;
00532 pk11_context_t *pk11_ctx;
00533 isc_result_t ret;
00534 unsigned int i;
00535
00536 UNUSED(unused);
00537 UNUSED(callback);
00538
00539 pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
00540 sizeof(*pk11_ctx));
00541 if (pk11_ctx == NULL)
00542 return (ISC_R_NOMEMORY);
00543 ret = pk11_get_session(pk11_ctx, OP_DSA, ISC_TRUE, ISC_FALSE,
00544 ISC_FALSE, NULL, pk11_get_best_token(OP_DSA));
00545 if (ret != ISC_R_SUCCESS)
00546 goto err;
00547
00548 bits = key->key_size;
00549 PK11_RET(pkcs_C_GenerateKey,
00550 (pk11_ctx->session, &mech, dpTemplate, (CK_ULONG) 5, &dp),
00551 DST_R_CRYPTOFAILURE);
00552
00553 dsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dsa));
00554 if (dsa == NULL)
00555 DST_RET(ISC_R_NOMEMORY);
00556 memset(dsa, 0, sizeof(*dsa));
00557 key->keydata.pkey = dsa;
00558 dsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 5);
00559 if (dsa->repr == NULL)
00560 DST_RET(ISC_R_NOMEMORY);
00561 memset(dsa->repr, 0, sizeof(*attr) * 5);
00562 dsa->attrcnt = 5;
00563
00564 attr = dsa->repr;
00565 attr[0].type = CKA_PRIME;
00566 attr[1].type = CKA_SUBPRIME;
00567 attr[2].type = CKA_BASE;
00568 attr[3].type = CKA_VALUE;
00569 attr[4].type = CKA_VALUE2;
00570
00571 PK11_RET(pkcs_C_GetAttributeValue,
00572 (pk11_ctx->session, dp, attr, 3),
00573 DST_R_CRYPTOFAILURE);
00574
00575 for (i = 0; i <= 2; i++) {
00576 attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen);
00577 if (attr[i].pValue == NULL)
00578 DST_RET(ISC_R_NOMEMORY);
00579 memset(attr[i].pValue, 0, attr[i].ulValueLen);
00580 }
00581 PK11_RET(pkcs_C_GetAttributeValue,
00582 (pk11_ctx->session, dp, attr, 3),
00583 DST_R_CRYPTOFAILURE);
00584 pubTemplate[5].pValue = attr[0].pValue;
00585 pubTemplate[5].ulValueLen = attr[0].ulValueLen;
00586 pubTemplate[6].pValue = attr[1].pValue;
00587 pubTemplate[6].ulValueLen = attr[1].ulValueLen;
00588 pubTemplate[7].pValue = attr[2].pValue;
00589 pubTemplate[7].ulValueLen = attr[2].ulValueLen;
00590
00591 mech.mechanism = CKM_DSA_KEY_PAIR_GEN;
00592 PK11_RET(pkcs_C_GenerateKeyPair,
00593 (pk11_ctx->session, &mech,
00594 pubTemplate, (CK_ULONG) 8,
00595 privTemplate, (CK_ULONG) 7,
00596 &pub, &priv),
00597 DST_R_CRYPTOFAILURE);
00598
00599 attr = dsa->repr;
00600 attr += 3;
00601 PK11_RET(pkcs_C_GetAttributeValue,
00602 (pk11_ctx->session, pub, attr, 1),
00603 DST_R_CRYPTOFAILURE);
00604 attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen);
00605 if (attr->pValue == NULL)
00606 DST_RET(ISC_R_NOMEMORY);
00607 memset(attr->pValue, 0, attr->ulValueLen);
00608 PK11_RET(pkcs_C_GetAttributeValue,
00609 (pk11_ctx->session, pub, attr, 1),
00610 DST_R_CRYPTOFAILURE);
00611
00612 attr++;
00613 attr->type = CKA_VALUE;
00614 PK11_RET(pkcs_C_GetAttributeValue,
00615 (pk11_ctx->session, priv, attr, 1),
00616 DST_R_CRYPTOFAILURE);
00617 attr->pValue = isc_mem_get(key->mctx, attr->ulValueLen);
00618 if (attr->pValue == NULL)
00619 DST_RET(ISC_R_NOMEMORY);
00620 memset(attr->pValue, 0, attr->ulValueLen);
00621 PK11_RET(pkcs_C_GetAttributeValue,
00622 (pk11_ctx->session, priv, attr, 1),
00623 DST_R_CRYPTOFAILURE);
00624 attr->type = CKA_VALUE2;
00625
00626 (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
00627 (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
00628 (void) pkcs_C_DestroyObject(pk11_ctx->session, dp);
00629 pk11_return_session(pk11_ctx);
00630 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00631 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
00632
00633 return (ISC_R_SUCCESS);
00634
00635 err:
00636 pkcs11dsa_destroy(key);
00637 if (priv != CK_INVALID_HANDLE)
00638 (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
00639 if (pub != CK_INVALID_HANDLE)
00640 (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
00641 if (dp != CK_INVALID_HANDLE)
00642 (void) pkcs_C_DestroyObject(pk11_ctx->session, dp);
00643 pk11_return_session(pk11_ctx);
00644 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00645 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
00646
00647 return (ret);
00648 }
00649
00650 static isc_boolean_t
00651 pkcs11dsa_isprivate(const dst_key_t *key) {
00652 pk11_object_t *dsa = key->keydata.pkey;
00653 CK_ATTRIBUTE *attr;
00654
00655 if (dsa == NULL)
00656 return (ISC_FALSE);
00657 attr = pk11_attribute_bytype(dsa, CKA_VALUE2);
00658 return (ISC_TF((attr != NULL) || dsa->ontoken));
00659 }
00660
00661 static void
00662 pkcs11dsa_destroy(dst_key_t *key) {
00663 pk11_object_t *dsa = key->keydata.pkey;
00664 CK_ATTRIBUTE *attr;
00665
00666 if (dsa == NULL)
00667 return;
00668
00669 INSIST((dsa->object == CK_INVALID_HANDLE) || dsa->ontoken);
00670
00671 for (attr = pk11_attribute_first(dsa);
00672 attr != NULL;
00673 attr = pk11_attribute_next(dsa, attr))
00674 switch (attr->type) {
00675 case CKA_PRIME:
00676 case CKA_SUBPRIME:
00677 case CKA_BASE:
00678 case CKA_VALUE:
00679 case CKA_VALUE2:
00680 if (attr->pValue != NULL) {
00681 memset(attr->pValue, 0, attr->ulValueLen);
00682 isc_mem_put(key->mctx,
00683 attr->pValue,
00684 attr->ulValueLen);
00685 }
00686 break;
00687 }
00688 if (dsa->repr != NULL) {
00689 memset(dsa->repr, 0, dsa->attrcnt * sizeof(*attr));
00690 isc_mem_put(key->mctx,
00691 dsa->repr,
00692 dsa->attrcnt * sizeof(*attr));
00693 }
00694 memset(dsa, 0, sizeof(*dsa));
00695 isc_mem_put(key->mctx, dsa, sizeof(*dsa));
00696 key->keydata.pkey = NULL;
00697 }
00698
00699
00700 static isc_result_t
00701 pkcs11dsa_todns(const dst_key_t *key, isc_buffer_t *data) {
00702 pk11_object_t *dsa;
00703 CK_ATTRIBUTE *attr;
00704 isc_region_t r;
00705 int dnslen;
00706 unsigned int t, p_bytes;
00707 CK_ATTRIBUTE *prime = NULL, *subprime = NULL;
00708 CK_ATTRIBUTE *base = NULL, *pub_key = NULL;
00709 CK_BYTE *cp;
00710
00711 REQUIRE(key->keydata.pkey != NULL);
00712
00713 dsa = key->keydata.pkey;
00714
00715 for (attr = pk11_attribute_first(dsa);
00716 attr != NULL;
00717 attr = pk11_attribute_next(dsa, attr))
00718 switch (attr->type) {
00719 case CKA_PRIME:
00720 prime = attr;
00721 break;
00722 case CKA_SUBPRIME:
00723 subprime = attr;
00724 break;
00725 case CKA_BASE:
00726 base = attr;
00727 break;
00728 case CKA_VALUE:
00729 pub_key = attr;
00730 break;
00731 }
00732 REQUIRE((prime != NULL) && (subprime != NULL) &&
00733 (base != NULL) && (pub_key != NULL));
00734
00735 isc_buffer_availableregion(data, &r);
00736
00737 t = (prime->ulValueLen - 64) / 8;
00738 if (t > 8)
00739 return (DST_R_INVALIDPUBLICKEY);
00740 p_bytes = 64 + 8 * t;
00741
00742 dnslen = 1 + (key->key_size * 3)/8 + ISC_SHA1_DIGESTLENGTH;
00743 if (r.length < (unsigned int) dnslen)
00744 return (ISC_R_NOSPACE);
00745
00746 memset(r.base, 0, dnslen);
00747 *r.base++ = t;
00748 cp = (CK_BYTE *) subprime->pValue;
00749 memmove(r.base + ISC_SHA1_DIGESTLENGTH - subprime->ulValueLen,
00750 cp, subprime->ulValueLen);
00751 r.base += ISC_SHA1_DIGESTLENGTH;
00752 cp = (CK_BYTE *) prime->pValue;
00753 memmove(r.base + key->key_size/8 - prime->ulValueLen,
00754 cp, prime->ulValueLen);
00755 r.base += p_bytes;
00756 cp = (CK_BYTE *) base->pValue;
00757 memmove(r.base + key->key_size/8 - base->ulValueLen,
00758 cp, base->ulValueLen);
00759 r.base += p_bytes;
00760 cp = (CK_BYTE *) pub_key->pValue;
00761 memmove(r.base + key->key_size/8 - pub_key->ulValueLen,
00762 cp, pub_key->ulValueLen);
00763 r.base += p_bytes;
00764
00765 isc_buffer_add(data, dnslen);
00766
00767 return (ISC_R_SUCCESS);
00768 }
00769
00770 static isc_result_t
00771 pkcs11dsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
00772 pk11_object_t *dsa;
00773 isc_region_t r;
00774 unsigned int t, p_bytes;
00775 CK_BYTE *prime, *subprime, *base, *pub_key;
00776 CK_ATTRIBUTE *attr;
00777
00778 isc_buffer_remainingregion(data, &r);
00779 if (r.length == 0)
00780 return (ISC_R_SUCCESS);
00781
00782 dsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dsa));
00783 if (dsa == NULL)
00784 return (ISC_R_NOMEMORY);
00785 memset(dsa, 0, sizeof(*dsa));
00786
00787 t = (unsigned int) *r.base++;
00788 if (t > 8) {
00789 memset(dsa, 0, sizeof(*dsa));
00790 isc_mem_put(key->mctx, dsa, sizeof(*dsa));
00791 return (DST_R_INVALIDPUBLICKEY);
00792 }
00793 p_bytes = 64 + 8 * t;
00794
00795 if (r.length < 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes) {
00796 memset(dsa, 0, sizeof(*dsa));
00797 isc_mem_put(key->mctx, dsa, sizeof(*dsa));
00798 return (DST_R_INVALIDPUBLICKEY);
00799 }
00800
00801 subprime = r.base;
00802 r.base += ISC_SHA1_DIGESTLENGTH;
00803
00804 prime = r.base;
00805 r.base += p_bytes;
00806
00807 base = r.base;
00808 r.base += p_bytes;
00809
00810 pub_key = r.base;
00811 r.base += p_bytes;
00812
00813 key->key_size = p_bytes * 8;
00814
00815 isc_buffer_forward(data, 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes);
00816
00817 dsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 4);
00818 if (dsa->repr == NULL)
00819 goto nomemory;
00820 memset(dsa->repr, 0, sizeof(*attr) * 4);
00821 dsa->attrcnt = 4;
00822
00823 attr = dsa->repr;
00824 attr[0].type = CKA_PRIME;
00825 attr[0].pValue = isc_mem_get(key->mctx, p_bytes);
00826 if (attr[0].pValue == NULL)
00827 goto nomemory;
00828 memmove(attr[0].pValue, prime, p_bytes);
00829 attr[0].ulValueLen = p_bytes;
00830
00831 attr[1].type = CKA_SUBPRIME;
00832 attr[1].pValue = isc_mem_get(key->mctx, ISC_SHA1_DIGESTLENGTH);
00833 if (attr[1].pValue == NULL)
00834 goto nomemory;
00835 memmove(attr[1].pValue, subprime, ISC_SHA1_DIGESTLENGTH);
00836 attr[1].ulValueLen = ISC_SHA1_DIGESTLENGTH;
00837
00838 attr[2].type = CKA_BASE;
00839 attr[2].pValue = isc_mem_get(key->mctx, p_bytes);
00840 if (attr[2].pValue == NULL)
00841 goto nomemory;
00842 memmove(attr[2].pValue, base, p_bytes);
00843 attr[2].ulValueLen = p_bytes;
00844
00845 attr[3].type = CKA_VALUE;
00846 attr[3].pValue = isc_mem_get(key->mctx, p_bytes);
00847 if (attr[3].pValue == NULL)
00848 goto nomemory;
00849 memmove(attr[3].pValue, pub_key, p_bytes);
00850 attr[3].ulValueLen = p_bytes;
00851
00852 key->keydata.pkey = dsa;
00853
00854 return (ISC_R_SUCCESS);
00855
00856 nomemory:
00857 for (attr = pk11_attribute_first(dsa);
00858 attr != NULL;
00859 attr = pk11_attribute_next(dsa, attr))
00860 switch (attr->type) {
00861 case CKA_PRIME:
00862 case CKA_SUBPRIME:
00863 case CKA_BASE:
00864 case CKA_VALUE:
00865 if (attr->pValue != NULL) {
00866 memset(attr->pValue, 0, attr->ulValueLen);
00867 isc_mem_put(key->mctx,
00868 attr->pValue,
00869 attr->ulValueLen);
00870 }
00871 break;
00872 }
00873 if (dsa->repr != NULL) {
00874 memset(dsa->repr, 0, dsa->attrcnt * sizeof(*attr));
00875 isc_mem_put(key->mctx,
00876 dsa->repr,
00877 dsa->attrcnt * sizeof(*attr));
00878 }
00879 memset(dsa, 0, sizeof(*dsa));
00880 isc_mem_put(key->mctx, dsa, sizeof(*dsa));
00881 return (ISC_R_NOMEMORY);
00882 }
00883
00884 static isc_result_t
00885 pkcs11dsa_tofile(const dst_key_t *key, const char *directory) {
00886 int cnt = 0;
00887 pk11_object_t *dsa;
00888 CK_ATTRIBUTE *attr;
00889 CK_ATTRIBUTE *prime = NULL, *subprime = NULL, *base = NULL;
00890 CK_ATTRIBUTE *pub_key = NULL, *priv_key = NULL;
00891 dst_private_t priv;
00892 unsigned char bufs[5][128];
00893
00894 if (key->keydata.pkey == NULL)
00895 return (DST_R_NULLKEY);
00896
00897 if (key->external) {
00898 priv.nelements = 0;
00899 return (dst__privstruct_writefile(key, &priv, directory));
00900 }
00901
00902 dsa = key->keydata.pkey;
00903
00904 for (attr = pk11_attribute_first(dsa);
00905 attr != NULL;
00906 attr = pk11_attribute_next(dsa, attr))
00907 switch (attr->type) {
00908 case CKA_PRIME:
00909 prime = attr;
00910 break;
00911 case CKA_SUBPRIME:
00912 subprime = attr;
00913 break;
00914 case CKA_BASE:
00915 base = attr;
00916 break;
00917 case CKA_VALUE:
00918 pub_key = attr;
00919 break;
00920 case CKA_VALUE2:
00921 priv_key = attr;
00922 break;
00923 }
00924 if ((prime == NULL) || (subprime == NULL) || (base == NULL) ||
00925 (pub_key == NULL) || (priv_key ==NULL))
00926 return (DST_R_NULLKEY);
00927
00928 priv.elements[cnt].tag = TAG_DSA_PRIME;
00929 priv.elements[cnt].length = (unsigned short) prime->ulValueLen;
00930 memmove(bufs[cnt], prime->pValue, prime->ulValueLen);
00931 priv.elements[cnt].data = bufs[cnt];
00932 cnt++;
00933
00934 priv.elements[cnt].tag = TAG_DSA_SUBPRIME;
00935 priv.elements[cnt].length = (unsigned short) subprime->ulValueLen;
00936 memmove(bufs[cnt], subprime->pValue, subprime->ulValueLen);
00937 priv.elements[cnt].data = bufs[cnt];
00938 cnt++;
00939
00940 priv.elements[cnt].tag = TAG_DSA_BASE;
00941 priv.elements[cnt].length = (unsigned short) base->ulValueLen;
00942 memmove(bufs[cnt], base->pValue, base->ulValueLen);
00943 priv.elements[cnt].data = bufs[cnt];
00944 cnt++;
00945
00946 priv.elements[cnt].tag = TAG_DSA_PRIVATE;
00947 priv.elements[cnt].length = (unsigned short) priv_key->ulValueLen;
00948 memmove(bufs[cnt], priv_key->pValue, priv_key->ulValueLen);
00949 priv.elements[cnt].data = bufs[cnt];
00950 cnt++;
00951
00952 priv.elements[cnt].tag = TAG_DSA_PUBLIC;
00953 priv.elements[cnt].length = (unsigned short) pub_key->ulValueLen;
00954 memmove(bufs[cnt], pub_key->pValue, pub_key->ulValueLen);
00955 priv.elements[cnt].data = bufs[cnt];
00956 cnt++;
00957
00958 priv.nelements = cnt;
00959 return (dst__privstruct_writefile(key, &priv, directory));
00960 }
00961
00962 static isc_result_t
00963 pkcs11dsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
00964 dst_private_t priv;
00965 isc_result_t ret;
00966 int i;
00967 pk11_object_t *dsa = NULL;
00968 CK_ATTRIBUTE *attr;
00969 isc_mem_t *mctx = key->mctx;
00970
00971
00972 ret = dst__privstruct_parse(key, DST_ALG_DSA, lexer, mctx, &priv);
00973 if (ret != ISC_R_SUCCESS)
00974 return (ret);
00975
00976 if (key->external) {
00977 if (priv.nelements != 0)
00978 DST_RET(DST_R_INVALIDPRIVATEKEY);
00979 if (pub == NULL)
00980 DST_RET(DST_R_INVALIDPRIVATEKEY);
00981
00982 key->keydata.pkey = pub->keydata.pkey;
00983 pub->keydata.pkey = NULL;
00984 key->key_size = pub->key_size;
00985
00986 dst__privstruct_free(&priv, mctx);
00987 memset(&priv, 0, sizeof(priv));
00988
00989 return (ISC_R_SUCCESS);
00990 }
00991
00992 dsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dsa));
00993 if (dsa == NULL)
00994 DST_RET(ISC_R_NOMEMORY);
00995 memset(dsa, 0, sizeof(*dsa));
00996 key->keydata.pkey = dsa;
00997
00998 dsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 5);
00999 if (dsa->repr == NULL)
01000 DST_RET(ISC_R_NOMEMORY);
01001 memset(dsa->repr, 0, sizeof(*attr) * 5);
01002 dsa->attrcnt = 5;
01003 attr = dsa->repr;
01004 attr[0].type = CKA_PRIME;
01005 attr[1].type = CKA_SUBPRIME;
01006 attr[2].type = CKA_BASE;
01007 attr[3].type = CKA_VALUE;
01008 attr[4].type = CKA_VALUE2;
01009
01010 for (i = 0; i < priv.nelements; i++) {
01011 CK_BYTE *bn;
01012
01013 bn = isc_mem_get(key->mctx, priv.elements[i].length);
01014 if (bn == NULL)
01015 DST_RET(ISC_R_NOMEMORY);
01016 memmove(bn, priv.elements[i].data, priv.elements[i].length);
01017
01018 switch (priv.elements[i].tag) {
01019 case TAG_DSA_PRIME:
01020 attr = pk11_attribute_bytype(dsa, CKA_PRIME);
01021 INSIST(attr != NULL);
01022 attr->pValue = bn;
01023 attr->ulValueLen = priv.elements[i].length;
01024 break;
01025 case TAG_DSA_SUBPRIME:
01026 attr = pk11_attribute_bytype(dsa,
01027 CKA_SUBPRIME);
01028 INSIST(attr != NULL);
01029 attr->pValue = bn;
01030 attr->ulValueLen = priv.elements[i].length;
01031 break;
01032 case TAG_DSA_BASE:
01033 attr = pk11_attribute_bytype(dsa, CKA_BASE);
01034 INSIST(attr != NULL);
01035 attr->pValue = bn;
01036 attr->ulValueLen = priv.elements[i].length;
01037 break;
01038 case TAG_DSA_PRIVATE:
01039 attr = pk11_attribute_bytype(dsa, CKA_VALUE2);
01040 INSIST(attr != NULL);
01041 attr->pValue = bn;
01042 attr->ulValueLen = priv.elements[i].length;
01043 break;
01044 case TAG_DSA_PUBLIC:
01045 attr = pk11_attribute_bytype(dsa, CKA_VALUE);
01046 INSIST(attr != NULL);
01047 attr->pValue = bn;
01048 attr->ulValueLen = priv.elements[i].length;
01049 break;
01050 }
01051 }
01052 dst__privstruct_free(&priv, mctx);
01053
01054 attr = pk11_attribute_bytype(dsa, CKA_PRIME);
01055 INSIST(attr != NULL);
01056 key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);
01057
01058 return (ISC_R_SUCCESS);
01059
01060 err:
01061 pkcs11dsa_destroy(key);
01062 dst__privstruct_free(&priv, mctx);
01063 memset(&priv, 0, sizeof(priv));
01064 return (ret);
01065 }
01066
01067 static dst_func_t pkcs11dsa_functions = {
01068 pkcs11dsa_createctx,
01069 NULL,
01070 pkcs11dsa_destroyctx,
01071 pkcs11dsa_adddata,
01072 pkcs11dsa_sign,
01073 pkcs11dsa_verify,
01074 NULL,
01075 NULL,
01076 pkcs11dsa_compare,
01077 NULL,
01078 pkcs11dsa_generate,
01079 pkcs11dsa_isprivate,
01080 pkcs11dsa_destroy,
01081 pkcs11dsa_todns,
01082 pkcs11dsa_fromdns,
01083 pkcs11dsa_tofile,
01084 pkcs11dsa_parse,
01085 NULL,
01086 NULL,
01087 NULL,
01088 NULL,
01089 };
01090
01091 isc_result_t
01092 dst__pkcs11dsa_init(dst_func_t **funcp) {
01093 REQUIRE(funcp != NULL);
01094 if (*funcp == NULL)
01095 *funcp = &pkcs11dsa_functions;
01096 return (ISC_R_SUCCESS);
01097 }
01098
01099 #else
01100
01101 #include <isc/util.h>
01102
01103 EMPTY_TRANSLATION_UNIT
01104
01105 #endif
01106