pkcs11dh_link.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2014  Internet Systems Consortium, Inc. ("ISC")
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00013  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 /* $Id$ */
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  * PKCS#3 DH keys:
00044  *  mechanisms:
00045  *    CKM_DH_PKCS_PARAMETER_GEN,
00046  *    CKM_DH_PKCS_KEY_PAIR_GEN,
00047  *    CKM_DH_PKCS_DERIVE
00048  *  domain parameters:
00049  *    object class CKO_DOMAIN_PARAMETERS
00050  *    key type CKK_DH
00051  *    attribute CKA_PRIME (prime p)
00052  *    attribute CKA_BASE (base g)
00053  *    optional attribute CKA_PRIME_BITS (p length in bits)
00054  *  public key:
00055  *    object class CKO_PUBLIC_KEY
00056  *    key type CKK_DH
00057  *    attribute CKA_PRIME (prime p)
00058  *    attribute CKA_BASE (base g)
00059  *    attribute CKA_VALUE (public value y)
00060  *  private key:
00061  *    object class CKO_PRIVATE_KEY
00062  *    key type CKK_DH
00063  *    attribute CKA_PRIME (prime p)
00064  *    attribute CKA_BASE (base g)
00065  *    attribute CKA_VALUE (private value x)
00066  *    optional attribute CKA_VALUE_BITS (x length in bits)
00067  *  reuse CKA_PRIVATE_EXPONENT for key pair private value
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         /* strip leading zeros */
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          * Read the prime length.  1 & 2 are table entries, > 16 means a
00747          * prime follows, otherwise an error.
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          * Read the generator length.  This should be 0 if the prime was
00797          * special, but it might not be.  If it's 0 and the prime is not
00798          * special, we have a problem.
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         /* read private key file */
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, /*%< createctx */
01090         NULL, /*%< createctx2 */
01091         NULL, /*%< destroyctx */
01092         NULL, /*%< adddata */
01093         NULL, /*%< sign */
01094         NULL, /*%< verify */
01095         NULL, /*%< verify2 */
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, /*%< cleanup */
01107         NULL, /*%< fromlabel */
01108         NULL, /*%< dump */
01109         NULL, /*%< restore */
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 /* PKCS11CRYPTO */
01121 
01122 #include <isc/util.h>
01123 
01124 EMPTY_TRANSLATION_UNIT
01125 
01126 #endif /* PKCS11CRYPTO */
01127 /*! \file */

Generated on Tue Apr 28 17:40:58 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha