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