pkcs11rsa_link.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2014, 2015  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 <isc/entropy.h>
00024 #include <isc/md5.h>
00025 #include <isc/sha1.h>
00026 #include <isc/sha2.h>
00027 #include <isc/mem.h>
00028 #include <isc/string.h>
00029 #include <isc/util.h>
00030 
00031 #include <dst/result.h>
00032 
00033 #include "dst_internal.h"
00034 #include "dst_parse.h"
00035 #include "dst_pkcs11.h"
00036 
00037 #include <pk11/internal.h>
00038 
00039 /*
00040  * Limit the size of public exponents.
00041  */
00042 #ifndef RSA_MAX_PUBEXP_BITS
00043 #define RSA_MAX_PUBEXP_BITS    35
00044 #endif
00045 
00046 #define DST_RET(a) {ret = a; goto err;}
00047 
00048 static CK_BBOOL truevalue = TRUE;
00049 static CK_BBOOL falsevalue = FALSE;
00050 
00051 static isc_result_t pkcs11rsa_todns(const dst_key_t *key, isc_buffer_t *data);
00052 static void pkcs11rsa_destroy(dst_key_t *key);
00053 static isc_result_t pkcs11rsa_fetch(dst_key_t *key, const char *engine,
00054                                     const char *label, dst_key_t *pub);
00055 
00056 static isc_result_t
00057 pkcs11rsa_createctx_sign(dst_key_t *key, dst_context_t *dctx) {
00058         CK_RV rv;
00059         CK_MECHANISM mech = { 0, NULL, 0 };
00060         CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
00061         CK_KEY_TYPE keyType = CKK_RSA;
00062         CK_ATTRIBUTE keyTemplate[] =
00063         {
00064                 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
00065                 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
00066                 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00067                 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00068                 { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00069                 { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
00070                 { CKA_MODULUS, NULL, 0 },
00071                 { CKA_PUBLIC_EXPONENT, NULL, 0 },
00072                 { CKA_PRIVATE_EXPONENT, NULL, 0 },
00073                 { CKA_PRIME_1, NULL, 0 },
00074                 { CKA_PRIME_2, NULL, 0 },
00075                 { CKA_EXPONENT_1, NULL, 0 },
00076                 { CKA_EXPONENT_2, NULL, 0 },
00077                 { CKA_COEFFICIENT, NULL, 0 }
00078         };
00079         CK_ATTRIBUTE *attr;
00080         CK_SLOT_ID slotid;
00081         pk11_object_t *rsa;
00082         pk11_context_t *pk11_ctx;
00083         isc_result_t ret;
00084         unsigned int i;
00085 
00086         REQUIRE(key->key_alg == DST_ALG_RSAMD5 ||
00087                 key->key_alg == DST_ALG_RSASHA1 ||
00088                 key->key_alg == DST_ALG_NSEC3RSASHA1 ||
00089                 key->key_alg == DST_ALG_RSASHA256 ||
00090                 key->key_alg == DST_ALG_RSASHA512);
00091 
00092         rsa = key->keydata.pkey;
00093 
00094         pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx,
00095                                                   sizeof(*pk11_ctx));
00096         if (pk11_ctx == NULL)
00097                 return (ISC_R_NOMEMORY);
00098         memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00099         if (rsa->ontoken)
00100                 slotid = rsa->slot;
00101         else
00102                 slotid = pk11_get_best_token(OP_RSA);
00103         ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE,
00104                                rsa->reqlogon, NULL, slotid);
00105         if (ret != ISC_R_SUCCESS)
00106                 goto err;
00107 
00108         if (rsa->ontoken && (rsa->object != CK_INVALID_HANDLE)) {
00109                 pk11_ctx->ontoken = rsa->ontoken;
00110                 pk11_ctx->object = rsa->object;
00111                 goto token_key;
00112         }
00113 
00114         for (attr = pk11_attribute_first(rsa);
00115              attr != NULL;
00116              attr = pk11_attribute_next(rsa, attr))
00117                 switch (attr->type) {
00118                 case CKA_MODULUS:
00119                         INSIST(keyTemplate[6].type == attr->type);
00120                         keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
00121                                                             attr->ulValueLen);
00122                         if (keyTemplate[6].pValue == NULL)
00123                                 DST_RET(ISC_R_NOMEMORY);
00124                         memmove(keyTemplate[6].pValue, attr->pValue,
00125                                 attr->ulValueLen);
00126                         keyTemplate[6].ulValueLen = attr->ulValueLen;
00127                         break;
00128                 case CKA_PUBLIC_EXPONENT:
00129                         INSIST(keyTemplate[7].type == attr->type);
00130                         keyTemplate[7].pValue = isc_mem_get(dctx->mctx,
00131                                                             attr->ulValueLen);
00132                         if (keyTemplate[7].pValue == NULL)
00133                                 DST_RET(ISC_R_NOMEMORY);
00134                         memmove(keyTemplate[7].pValue, attr->pValue,
00135                                 attr->ulValueLen);
00136                         keyTemplate[7].ulValueLen = attr->ulValueLen;
00137                         break;
00138                 case CKA_PRIVATE_EXPONENT:
00139                         INSIST(keyTemplate[8].type == attr->type);
00140                         keyTemplate[8].pValue = isc_mem_get(dctx->mctx,
00141                                                             attr->ulValueLen);
00142                         if (keyTemplate[8].pValue == NULL)
00143                                 DST_RET(ISC_R_NOMEMORY);
00144                         memmove(keyTemplate[8].pValue, attr->pValue,
00145                                 attr->ulValueLen);
00146                         keyTemplate[8].ulValueLen = attr->ulValueLen;
00147                         break;
00148                 case CKA_PRIME_1:
00149                         INSIST(keyTemplate[9].type == attr->type);
00150                         keyTemplate[9].pValue = isc_mem_get(dctx->mctx,
00151                                                             attr->ulValueLen);
00152                         if (keyTemplate[9].pValue == NULL)
00153                                 DST_RET(ISC_R_NOMEMORY);
00154                         memmove(keyTemplate[9].pValue, attr->pValue,
00155                                 attr->ulValueLen);
00156                         keyTemplate[9].ulValueLen = attr->ulValueLen;
00157                         break;
00158                 case CKA_PRIME_2:
00159                         INSIST(keyTemplate[10].type == attr->type);
00160                         keyTemplate[10].pValue = isc_mem_get(dctx->mctx,
00161                                                             attr->ulValueLen);
00162                         if (keyTemplate[10].pValue == NULL)
00163                                 DST_RET(ISC_R_NOMEMORY);
00164                         memmove(keyTemplate[10].pValue, attr->pValue,
00165                                 attr->ulValueLen);
00166                         keyTemplate[10].ulValueLen = attr->ulValueLen;
00167                         break;
00168                 case CKA_EXPONENT_1:
00169                         INSIST(keyTemplate[11].type == attr->type);
00170                         keyTemplate[11].pValue = isc_mem_get(dctx->mctx,
00171                                                              attr->ulValueLen);
00172                         if (keyTemplate[11].pValue == NULL)
00173                                 DST_RET(ISC_R_NOMEMORY);
00174                         memmove(keyTemplate[11].pValue, attr->pValue,
00175                                 attr->ulValueLen);
00176                         keyTemplate[11].ulValueLen = attr->ulValueLen;
00177                         break;
00178                 case CKA_EXPONENT_2:
00179                         INSIST(keyTemplate[12].type == attr->type);
00180                         keyTemplate[12].pValue = isc_mem_get(dctx->mctx,
00181                                                              attr->ulValueLen);
00182                         if (keyTemplate[12].pValue == NULL)
00183                                 DST_RET(ISC_R_NOMEMORY);
00184                         memmove(keyTemplate[12].pValue, attr->pValue,
00185                                 attr->ulValueLen);
00186                         keyTemplate[12].ulValueLen = attr->ulValueLen;
00187                         break;
00188                 case CKA_COEFFICIENT:
00189                         INSIST(keyTemplate[13].type == attr->type);
00190                         keyTemplate[13].pValue = isc_mem_get(dctx->mctx,
00191                                                              attr->ulValueLen);
00192                         if (keyTemplate[13].pValue == NULL)
00193                                 DST_RET(ISC_R_NOMEMORY);
00194                         memmove(keyTemplate[13].pValue, attr->pValue,
00195                                 attr->ulValueLen);
00196                         keyTemplate[13].ulValueLen = attr->ulValueLen;
00197                         break;
00198                 }
00199         pk11_ctx->object = CK_INVALID_HANDLE;
00200         pk11_ctx->ontoken = ISC_FALSE;
00201         PK11_RET(pkcs_C_CreateObject,
00202                  (pk11_ctx->session,
00203                   keyTemplate, (CK_ULONG) 14,
00204                   &pk11_ctx->object),
00205                  ISC_R_FAILURE);
00206 
00207     token_key:
00208 
00209         switch (dctx->key->key_alg) {
00210         case DST_ALG_RSAMD5:
00211                 mech.mechanism = CKM_MD5_RSA_PKCS;
00212                 break;
00213         case DST_ALG_RSASHA1:
00214         case DST_ALG_NSEC3RSASHA1:
00215                 mech.mechanism = CKM_SHA1_RSA_PKCS;
00216                 break;
00217         case DST_ALG_RSASHA256:
00218                 mech.mechanism = CKM_SHA256_RSA_PKCS;
00219                 break;
00220         case DST_ALG_RSASHA512:
00221                 mech.mechanism = CKM_SHA512_RSA_PKCS;
00222                 break;
00223         default:
00224                 INSIST(0);
00225         }
00226 
00227         PK11_RET(pkcs_C_SignInit,
00228                  (pk11_ctx->session, &mech, pk11_ctx->object),
00229                  ISC_R_FAILURE);
00230 
00231         dctx->ctxdata.pk11_ctx = pk11_ctx;
00232 
00233         for (i = 6; i <= 13; i++)
00234                 if (keyTemplate[i].pValue != NULL) {
00235                         memset(keyTemplate[i].pValue, 0,
00236                                keyTemplate[i].ulValueLen);
00237                         isc_mem_put(dctx->mctx,
00238                                     keyTemplate[i].pValue,
00239                                     keyTemplate[i].ulValueLen);
00240                 }
00241 
00242         return (ISC_R_SUCCESS);
00243 
00244     err:
00245         if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE))
00246                 (void) pkcs_C_DestroyObject(pk11_ctx->session,
00247                                             pk11_ctx->object);
00248         for (i = 6; i <= 13; i++)
00249                 if (keyTemplate[i].pValue != NULL) {
00250                         memset(keyTemplate[i].pValue, 0,
00251                                keyTemplate[i].ulValueLen);
00252                         isc_mem_put(dctx->mctx,
00253                                     keyTemplate[i].pValue,
00254                                     keyTemplate[i].ulValueLen);
00255                 }
00256         pk11_return_session(pk11_ctx);
00257         memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00258         isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
00259 
00260         return (ret);
00261 }
00262 
00263 static isc_result_t
00264 pkcs11rsa_createctx_verify(dst_key_t *key, unsigned int maxbits,
00265                            dst_context_t *dctx) {
00266         CK_RV rv;
00267         CK_MECHANISM mech = { 0, NULL, 0 };
00268         CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
00269         CK_KEY_TYPE keyType = CKK_RSA;
00270         CK_ATTRIBUTE keyTemplate[] =
00271         {
00272                 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
00273                 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
00274                 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00275                 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00276                 { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
00277                 { CKA_MODULUS, NULL, 0 },
00278                 { CKA_PUBLIC_EXPONENT, NULL, 0 },
00279         };
00280         CK_ATTRIBUTE *attr;
00281         pk11_object_t *rsa;
00282         pk11_context_t *pk11_ctx;
00283         isc_result_t ret;
00284         unsigned int i;
00285 
00286         REQUIRE(key->key_alg == DST_ALG_RSAMD5 ||
00287                 key->key_alg == DST_ALG_RSASHA1 ||
00288                 key->key_alg == DST_ALG_NSEC3RSASHA1 ||
00289                 key->key_alg == DST_ALG_RSASHA256 ||
00290                 key->key_alg == DST_ALG_RSASHA512);
00291 
00292         rsa = key->keydata.pkey;
00293 
00294         pk11_ctx = (pk11_context_t *) isc_mem_get(dctx->mctx,
00295                                                   sizeof(*pk11_ctx));
00296         if (pk11_ctx == NULL)
00297                 return (ISC_R_NOMEMORY);
00298         ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE,
00299                                rsa->reqlogon, NULL,
00300                                pk11_get_best_token(OP_RSA));
00301         if (ret != ISC_R_SUCCESS)
00302                 goto err;
00303 
00304         for (attr = pk11_attribute_first(rsa);
00305              attr != NULL;
00306              attr = pk11_attribute_next(rsa, attr))
00307                 switch (attr->type) {
00308                 case CKA_MODULUS:
00309                         INSIST(keyTemplate[5].type == attr->type);
00310                         keyTemplate[5].pValue = isc_mem_get(dctx->mctx,
00311                                                             attr->ulValueLen);
00312                         if (keyTemplate[5].pValue == NULL)
00313                                 DST_RET(ISC_R_NOMEMORY);
00314                         memmove(keyTemplate[5].pValue, attr->pValue,
00315                                 attr->ulValueLen);
00316                         keyTemplate[5].ulValueLen = attr->ulValueLen;
00317                         break;
00318                 case CKA_PUBLIC_EXPONENT:
00319                         INSIST(keyTemplate[6].type == attr->type);
00320                         keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
00321                                                             attr->ulValueLen);
00322                         if (keyTemplate[6].pValue == NULL)
00323                                 DST_RET(ISC_R_NOMEMORY);
00324                         memmove(keyTemplate[6].pValue, attr->pValue,
00325                                 attr->ulValueLen);
00326                         keyTemplate[6].ulValueLen = attr->ulValueLen;
00327                         if (pk11_numbits(attr->pValue,
00328                                          attr->ulValueLen) > maxbits &&
00329                             maxbits != 0)
00330                                 DST_RET(DST_R_VERIFYFAILURE);
00331                         break;
00332                 }
00333         pk11_ctx->object = CK_INVALID_HANDLE;
00334         pk11_ctx->ontoken = ISC_FALSE;
00335         PK11_RET(pkcs_C_CreateObject,
00336                  (pk11_ctx->session,
00337                   keyTemplate, (CK_ULONG) 7,
00338                   &pk11_ctx->object),
00339                  ISC_R_FAILURE);
00340 
00341         switch (dctx->key->key_alg) {
00342         case DST_ALG_RSAMD5:
00343                 mech.mechanism = CKM_MD5_RSA_PKCS;
00344                 break;
00345         case DST_ALG_RSASHA1:
00346         case DST_ALG_NSEC3RSASHA1:
00347                 mech.mechanism = CKM_SHA1_RSA_PKCS;
00348                 break;
00349         case DST_ALG_RSASHA256:
00350                 mech.mechanism = CKM_SHA256_RSA_PKCS;
00351                 break;
00352         case DST_ALG_RSASHA512:
00353                 mech.mechanism = CKM_SHA512_RSA_PKCS;
00354                 break;
00355         default:
00356                 INSIST(0);
00357         }
00358 
00359         PK11_RET(pkcs_C_VerifyInit,
00360                  (pk11_ctx->session, &mech, pk11_ctx->object),
00361                  ISC_R_FAILURE);
00362 
00363         dctx->ctxdata.pk11_ctx = pk11_ctx;
00364 
00365         for (i = 5; i <= 6; i++)
00366                 if (keyTemplate[i].pValue != NULL) {
00367                         memset(keyTemplate[i].pValue, 0,
00368                                keyTemplate[i].ulValueLen);
00369                         isc_mem_put(dctx->mctx,
00370                                     keyTemplate[i].pValue,
00371                                     keyTemplate[i].ulValueLen);
00372                 }
00373 
00374         return (ISC_R_SUCCESS);
00375 
00376     err:
00377         if (!pk11_ctx->ontoken && (pk11_ctx->object != CK_INVALID_HANDLE))
00378                 (void) pkcs_C_DestroyObject(pk11_ctx->session,
00379                                             pk11_ctx->object);
00380         for (i = 5; i <= 6; i++)
00381                 if (keyTemplate[i].pValue != NULL) {
00382                         memset(keyTemplate[i].pValue, 0,
00383                                keyTemplate[i].ulValueLen);
00384                         isc_mem_put(dctx->mctx,
00385                                     keyTemplate[i].pValue,
00386                                     keyTemplate[i].ulValueLen);
00387                 }
00388         pk11_return_session(pk11_ctx);
00389         memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00390         isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
00391 
00392         return (ret);
00393 }
00394 
00395 static isc_result_t
00396 pkcs11rsa_createctx(dst_key_t *key, dst_context_t *dctx) {
00397         if (dctx->use == DO_SIGN)
00398                 return (pkcs11rsa_createctx_sign(key, dctx));
00399         else
00400                 return (pkcs11rsa_createctx_verify(key, 0U, dctx));
00401 }
00402 
00403 static isc_result_t
00404 pkcs11rsa_createctx2(dst_key_t *key, int maxbits, dst_context_t *dctx) {
00405         if (dctx->use == DO_SIGN)
00406                 return (pkcs11rsa_createctx_sign(key, dctx));
00407         else
00408                 return (pkcs11rsa_createctx_verify(key,
00409                                                    (unsigned) maxbits, dctx));
00410 }
00411 
00412 static void
00413 pkcs11rsa_destroyctx(dst_context_t *dctx) {
00414         pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
00415 
00416         if (pk11_ctx != NULL) {
00417                 if (!pk11_ctx->ontoken &&
00418                     (pk11_ctx->object != CK_INVALID_HANDLE))
00419                         (void) pkcs_C_DestroyObject(pk11_ctx->session,
00420                                                     pk11_ctx->object);
00421                 pk11_return_session(pk11_ctx);
00422                 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00423                 isc_mem_put(dctx->mctx, pk11_ctx, sizeof(*pk11_ctx));
00424                 dctx->ctxdata.pk11_ctx = NULL;
00425         }
00426 }
00427 
00428 static isc_result_t
00429 pkcs11rsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
00430         CK_RV rv;
00431         pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
00432         isc_result_t ret = ISC_R_SUCCESS;
00433 
00434         if (dctx->use == DO_SIGN)
00435                 PK11_CALL(pkcs_C_SignUpdate,
00436                           (pk11_ctx->session,
00437                            (CK_BYTE_PTR) data->base,
00438                            (CK_ULONG) data->length),
00439                           ISC_R_FAILURE);
00440         else
00441                 PK11_CALL(pkcs_C_VerifyUpdate,
00442                           (pk11_ctx->session,
00443                            (CK_BYTE_PTR) data->base,
00444                            (CK_ULONG) data->length),
00445                           ISC_R_FAILURE);
00446         return (ret);
00447 }
00448 
00449 static isc_result_t
00450 pkcs11rsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
00451         CK_RV rv;
00452         CK_ULONG siglen = 0;
00453         isc_region_t r;
00454         pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
00455         isc_result_t ret = ISC_R_SUCCESS;
00456 
00457         PK11_RET(pkcs_C_SignFinal,
00458                  (pk11_ctx->session, NULL, &siglen),
00459                  DST_R_SIGNFAILURE);
00460 
00461         isc_buffer_availableregion(sig, &r);
00462 
00463         if (r.length < (unsigned int) siglen)
00464                 return (ISC_R_NOSPACE);
00465 
00466         PK11_RET(pkcs_C_SignFinal,
00467                  (pk11_ctx->session, (CK_BYTE_PTR) r.base, &siglen),
00468                  DST_R_SIGNFAILURE);
00469 
00470         isc_buffer_add(sig, (unsigned int) siglen);
00471 
00472     err:
00473         return (ret);
00474 }
00475 
00476 static isc_result_t
00477 pkcs11rsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
00478         CK_RV rv;
00479         pk11_context_t *pk11_ctx = dctx->ctxdata.pk11_ctx;
00480         isc_result_t ret = ISC_R_SUCCESS;
00481 
00482         PK11_CALL(pkcs_C_VerifyFinal,
00483                   (pk11_ctx->session,
00484                    (CK_BYTE_PTR) sig->base,
00485                    (CK_ULONG) sig->length),
00486                   DST_R_VERIFYFAILURE);
00487         return (ret);
00488 }
00489 
00490 static isc_boolean_t
00491 pkcs11rsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
00492         pk11_object_t *rsa1, *rsa2;
00493         CK_ATTRIBUTE *attr1, *attr2;
00494 
00495         rsa1 = key1->keydata.pkey;
00496         rsa2 = key2->keydata.pkey;
00497 
00498         if ((rsa1 == NULL) && (rsa2 == NULL))
00499                 return (ISC_TRUE);
00500         else if ((rsa1 == NULL) || (rsa2 == NULL))
00501                 return (ISC_FALSE);
00502 
00503         attr1 = pk11_attribute_bytype(rsa1, CKA_MODULUS);
00504         attr2 = pk11_attribute_bytype(rsa2, CKA_MODULUS);
00505         if ((attr1 == NULL) && (attr2 == NULL))
00506                 return (ISC_TRUE);
00507         else if ((attr1 == NULL) || (attr2 == NULL) ||
00508                  (attr1->ulValueLen != attr2->ulValueLen) ||
00509                  memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
00510                 return (ISC_FALSE);
00511 
00512         attr1 = pk11_attribute_bytype(rsa1, CKA_PUBLIC_EXPONENT);
00513         attr2 = pk11_attribute_bytype(rsa2, CKA_PUBLIC_EXPONENT);
00514         if ((attr1 == NULL) && (attr2 == NULL))
00515                 return (ISC_TRUE);
00516         else if ((attr1 == NULL) || (attr2 == NULL) ||
00517                  (attr1->ulValueLen != attr2->ulValueLen) ||
00518                  memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
00519                 return (ISC_FALSE);
00520 
00521         attr1 = pk11_attribute_bytype(rsa1, CKA_PRIVATE_EXPONENT);
00522         attr2 = pk11_attribute_bytype(rsa2, CKA_PRIVATE_EXPONENT);
00523         if (((attr1 != NULL) || (attr2 != NULL)) &&
00524             ((attr1 == NULL) || (attr2 == NULL) ||
00525              (attr1->ulValueLen != attr2->ulValueLen) ||
00526              memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)))
00527                 return (ISC_FALSE);
00528 
00529         if (!rsa1->ontoken && !rsa2->ontoken)
00530                 return (ISC_TRUE);
00531         else if (rsa1->ontoken || rsa2->ontoken ||
00532                  (rsa1->object != rsa2->object))
00533                 return (ISC_FALSE);
00534 
00535         return (ISC_TRUE);
00536 }
00537 
00538 static isc_result_t
00539 pkcs11rsa_generate(dst_key_t *key, int exp, void (*callback)(int)) {
00540         CK_RV rv;
00541         CK_MECHANISM mech = { CKM_RSA_PKCS_KEY_PAIR_GEN, NULL, 0 };
00542         CK_OBJECT_HANDLE pub = CK_INVALID_HANDLE;
00543         CK_ULONG bits = 0;
00544         CK_BYTE pubexp[5];
00545         CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
00546         CK_KEY_TYPE  keyType = CKK_RSA;
00547         CK_ATTRIBUTE pubTemplate[] =
00548         {
00549                 { CKA_CLASS, &pubClass, (CK_ULONG) sizeof(pubClass) },
00550                 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
00551                 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00552                 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00553                 { CKA_VERIFY, &truevalue, (CK_ULONG) sizeof(truevalue) },
00554                 { CKA_MODULUS_BITS, &bits, (CK_ULONG) sizeof(bits) },
00555                 { CKA_PUBLIC_EXPONENT, &pubexp, (CK_ULONG) sizeof(pubexp) }
00556         };
00557         CK_OBJECT_HANDLE priv = CK_INVALID_HANDLE;
00558         CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
00559         CK_ATTRIBUTE privTemplate[] =
00560         {
00561                 { CKA_CLASS, &privClass, (CK_ULONG) sizeof(privClass) },
00562                 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
00563                 { CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00564                 { CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00565                 { CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
00566                 { CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) },
00567                 { CKA_SIGN, &truevalue, (CK_ULONG) sizeof(truevalue) },
00568         };
00569         CK_ATTRIBUTE *attr;
00570         pk11_object_t *rsa;
00571         pk11_context_t *pk11_ctx;
00572         isc_result_t ret;
00573         unsigned int i;
00574 
00575         UNUSED(callback);
00576 
00577         pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
00578                                                   sizeof(*pk11_ctx));
00579         if (pk11_ctx == NULL)
00580                 return (ISC_R_NOMEMORY);
00581         ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE,
00582                                ISC_FALSE, NULL, pk11_get_best_token(OP_RSA));
00583         if (ret != ISC_R_SUCCESS)
00584                 goto err;
00585 
00586         bits = key->key_size;
00587         if (exp == 0) {
00588                 /* RSA_F4 0x10001 */
00589                 pubexp[0] = 1;
00590                 pubexp[1] = 0;
00591                 pubexp[2] = 1;
00592                 pubTemplate[6].ulValueLen = 3;
00593         } else {
00594                 /* F5 0x100000001 */
00595                 pubexp[0] = 1;
00596                 pubexp[1] = 0;
00597                 pubexp[2] = 0;
00598                 pubexp[3] = 0;
00599                 pubexp[4] = 1;
00600                 pubTemplate[6].ulValueLen = 5;
00601         }
00602 
00603         PK11_RET(pkcs_C_GenerateKeyPair,
00604                  (pk11_ctx->session, &mech,
00605                   pubTemplate, (CK_ULONG) 7,
00606                   privTemplate, (CK_ULONG) 7,
00607                   &pub, &priv),
00608                  DST_R_CRYPTOFAILURE);
00609 
00610         rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa));
00611         if (rsa == NULL)
00612                 DST_RET(ISC_R_NOMEMORY);
00613         memset(rsa, 0, sizeof(*rsa));
00614         key->keydata.pkey = rsa;
00615         rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 8);
00616         if (rsa->repr == NULL)
00617                 DST_RET(ISC_R_NOMEMORY);
00618         memset(rsa->repr, 0, sizeof(*attr) * 8);
00619         rsa->attrcnt = 8;
00620 
00621         attr = rsa->repr;
00622         attr[0].type = CKA_MODULUS;
00623         attr[1].type = CKA_PUBLIC_EXPONENT;
00624         attr[2].type = CKA_PRIVATE_EXPONENT;
00625         attr[3].type = CKA_PRIME_1;
00626         attr[4].type = CKA_PRIME_2;
00627         attr[5].type = CKA_EXPONENT_1;
00628         attr[6].type = CKA_EXPONENT_2;
00629         attr[7].type = CKA_COEFFICIENT;
00630 
00631         PK11_RET(pkcs_C_GetAttributeValue,
00632                  (pk11_ctx->session, pub, attr, 2),
00633                  DST_R_CRYPTOFAILURE);
00634         for (i = 0; i <= 1; i++) {
00635                 attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen);
00636                 if (attr[i].pValue == NULL)
00637                         DST_RET(ISC_R_NOMEMORY);
00638                 memset(attr[i].pValue, 0, attr[i].ulValueLen);
00639         }
00640         PK11_RET(pkcs_C_GetAttributeValue,
00641                  (pk11_ctx->session, pub, attr, 2),
00642                  DST_R_CRYPTOFAILURE);
00643 
00644         attr += 2;
00645         PK11_RET(pkcs_C_GetAttributeValue,
00646                  (pk11_ctx->session, priv, attr, 6),
00647                  DST_R_CRYPTOFAILURE);
00648         for (i = 0; i <= 5; i++) {
00649                 attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen);
00650                 if (attr[i].pValue == NULL)
00651                         DST_RET(ISC_R_NOMEMORY);
00652                 memset(attr[i].pValue, 0, attr[i].ulValueLen);
00653         }
00654         PK11_RET(pkcs_C_GetAttributeValue,
00655                  (pk11_ctx->session, priv, attr, 6),
00656                  DST_R_CRYPTOFAILURE);
00657 
00658         (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
00659         (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
00660         pk11_return_session(pk11_ctx);
00661         memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00662         isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
00663 
00664         return (ISC_R_SUCCESS);
00665 
00666     err:
00667         pkcs11rsa_destroy(key);
00668         if (priv != CK_INVALID_HANDLE)
00669                 (void) pkcs_C_DestroyObject(pk11_ctx->session, priv);
00670         if (pub != CK_INVALID_HANDLE)
00671                 (void) pkcs_C_DestroyObject(pk11_ctx->session, pub);
00672         pk11_return_session(pk11_ctx);
00673         memset(pk11_ctx, 0, sizeof(*pk11_ctx));
00674         isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
00675 
00676         return (ret);
00677 }
00678 
00679 static isc_boolean_t
00680 pkcs11rsa_isprivate(const dst_key_t *key) {
00681         pk11_object_t *rsa = key->keydata.pkey;
00682         CK_ATTRIBUTE *attr;
00683 
00684         if (rsa == NULL)
00685                 return (ISC_FALSE);
00686         attr = pk11_attribute_bytype(rsa, CKA_PRIVATE_EXPONENT);
00687         return (ISC_TF((attr != NULL) || rsa->ontoken));
00688 }
00689 
00690 static void
00691 pkcs11rsa_destroy(dst_key_t *key) {
00692         pk11_object_t *rsa = key->keydata.pkey;
00693         CK_ATTRIBUTE *attr;
00694 
00695         if (rsa == NULL)
00696                 return;
00697 
00698         INSIST((rsa->object == CK_INVALID_HANDLE) || rsa->ontoken);
00699 
00700         for (attr = pk11_attribute_first(rsa);
00701              attr != NULL;
00702              attr = pk11_attribute_next(rsa, attr))
00703                 switch (attr->type) {
00704                 case CKA_LABEL:
00705                 case CKA_ID:
00706                 case CKA_MODULUS:
00707                 case CKA_PUBLIC_EXPONENT:
00708                 case CKA_PRIVATE_EXPONENT:
00709                 case CKA_PRIME_1:
00710                 case CKA_PRIME_2:
00711                 case CKA_EXPONENT_1:
00712                 case CKA_EXPONENT_2:
00713                 case CKA_COEFFICIENT:
00714                         if (attr->pValue != NULL) {
00715                                 memset(attr->pValue, 0, attr->ulValueLen);
00716                                 isc_mem_put(key->mctx,
00717                                             attr->pValue,
00718                                             attr->ulValueLen);
00719                         }
00720                         break;
00721                 }
00722         if (rsa->repr != NULL) {
00723                 memset(rsa->repr, 0, rsa->attrcnt * sizeof(*attr));
00724                 isc_mem_put(key->mctx,
00725                             rsa->repr,
00726                             rsa->attrcnt * sizeof(*attr));
00727         }
00728         memset(rsa, 0, sizeof(*rsa));
00729         isc_mem_put(key->mctx, rsa, sizeof(*rsa));
00730         key->keydata.pkey = NULL;
00731 }
00732 
00733 static isc_result_t
00734 pkcs11rsa_todns(const dst_key_t *key, isc_buffer_t *data) {
00735         pk11_object_t *rsa;
00736         CK_ATTRIBUTE *attr;
00737         isc_region_t r;
00738         unsigned int e_bytes = 0, mod_bytes = 0;
00739         CK_BYTE *exponent = NULL, *modulus = NULL;
00740 
00741         REQUIRE(key->keydata.pkey != NULL);
00742 
00743         rsa = key->keydata.pkey;
00744 
00745         for (attr = pk11_attribute_first(rsa);
00746              attr != NULL;
00747              attr = pk11_attribute_next(rsa, attr))
00748                 switch (attr->type) {
00749                 case CKA_PUBLIC_EXPONENT:
00750                         exponent = (CK_BYTE *) attr->pValue;
00751                         e_bytes = (unsigned int) attr->ulValueLen;
00752                         break;
00753                 case CKA_MODULUS:
00754                         modulus = (CK_BYTE *) attr->pValue;
00755                         mod_bytes = (unsigned int) attr->ulValueLen;
00756                         break;
00757                 }
00758         REQUIRE((exponent != NULL) && (modulus != NULL));
00759 
00760         isc_buffer_availableregion(data, &r);
00761 
00762         if (e_bytes < 256) {    /*%< key exponent is <= 2040 bits */
00763                 if (r.length < 1)
00764                         return (ISC_R_NOSPACE);
00765                 isc_buffer_putuint8(data, (isc_uint8_t) e_bytes);
00766                 isc_region_consume(&r, 1);
00767         } else {
00768                 if (r.length < 3)
00769                         return (ISC_R_NOSPACE);
00770                 isc_buffer_putuint8(data, 0);
00771                 isc_buffer_putuint16(data, (isc_uint16_t) e_bytes);
00772                 isc_region_consume(&r, 3);
00773         }
00774 
00775         if (r.length < e_bytes + mod_bytes)
00776                 return (ISC_R_NOSPACE);
00777 
00778         memmove(r.base, exponent, e_bytes);
00779         isc_region_consume(&r, e_bytes);
00780         memmove(r.base, modulus, mod_bytes);
00781 
00782         isc_buffer_add(data, e_bytes + mod_bytes);
00783 
00784         return (ISC_R_SUCCESS);
00785 }
00786 
00787 static isc_result_t
00788 pkcs11rsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
00789         pk11_object_t *rsa;
00790         isc_region_t r;
00791         unsigned int e_bytes, mod_bytes;
00792         CK_BYTE *exponent = NULL, *modulus = NULL;
00793         CK_ATTRIBUTE *attr;
00794 
00795         isc_buffer_remainingregion(data, &r);
00796         if (r.length == 0)
00797                 return (ISC_R_SUCCESS);
00798 
00799         rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa));
00800         if (rsa == NULL)
00801                 return (ISC_R_NOMEMORY);
00802         memset(rsa, 0, sizeof(*rsa));
00803 
00804         if (r.length < 1) {
00805                 memset(rsa, 0, sizeof(*rsa));
00806                 isc_mem_put(key->mctx, rsa, sizeof(*rsa));
00807                 return (DST_R_INVALIDPUBLICKEY);
00808         }
00809         e_bytes = *r.base++;
00810         r.length--;
00811 
00812         if (e_bytes == 0) {
00813                 if (r.length < 2) {
00814                         memset(rsa, 0, sizeof(*rsa));
00815                         isc_mem_put(key->mctx, rsa, sizeof(*rsa));
00816                         return (DST_R_INVALIDPUBLICKEY);
00817                 }
00818                 e_bytes = ((*r.base++) << 8);
00819                 e_bytes += *r.base++;
00820                 r.length -= 2;
00821         }
00822 
00823         if (r.length < e_bytes) {
00824                 memset(rsa, 0, sizeof(*rsa));
00825                 isc_mem_put(key->mctx, rsa, sizeof(*rsa));
00826                 return (DST_R_INVALIDPUBLICKEY);
00827         }
00828         exponent = r.base;
00829         r.base += e_bytes;
00830         r.length -= e_bytes;
00831         modulus = r.base;
00832         mod_bytes = r.length;
00833 
00834         key->key_size = pk11_numbits(modulus, mod_bytes);
00835 
00836         isc_buffer_forward(data, r.length);
00837 
00838         rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
00839         if (rsa->repr == NULL)
00840                 goto nomemory;
00841         memset(rsa->repr, 0, sizeof(*attr) * 2);
00842         rsa->attrcnt = 2;
00843         attr = rsa->repr;
00844         attr[0].type = CKA_MODULUS;
00845         attr[0].pValue = isc_mem_get(key->mctx, mod_bytes);
00846         if (attr[0].pValue == NULL)
00847                 goto nomemory;
00848         memmove(attr[0].pValue, modulus, mod_bytes);
00849         attr[0].ulValueLen = (CK_ULONG) mod_bytes;
00850         attr[1].type = CKA_PUBLIC_EXPONENT;
00851         attr[1].pValue = isc_mem_get(key->mctx, e_bytes);
00852         if (attr[1].pValue == NULL)
00853                 goto nomemory;
00854         memmove(attr[1].pValue, exponent, e_bytes);
00855         attr[1].ulValueLen = (CK_ULONG) e_bytes;
00856 
00857         key->keydata.pkey = rsa;
00858 
00859         return (ISC_R_SUCCESS);
00860 
00861     nomemory:
00862         for (attr = pk11_attribute_first(rsa);
00863              attr != NULL;
00864              attr = pk11_attribute_next(rsa, attr))
00865                 switch (attr->type) {
00866                 case CKA_MODULUS:
00867                 case CKA_PUBLIC_EXPONENT:
00868                         if (attr->pValue != NULL) {
00869                                 memset(attr->pValue, 0, attr->ulValueLen);
00870                                 isc_mem_put(key->mctx,
00871                                             attr->pValue,
00872                                             attr->ulValueLen);
00873                         }
00874                         break;
00875                 }
00876         if (rsa->repr != NULL) {
00877                 memset(rsa->repr, 0, rsa->attrcnt * sizeof(*attr));
00878                 isc_mem_put(key->mctx,
00879                             rsa->repr,
00880                             rsa->attrcnt * sizeof(*attr));
00881         }
00882         memset(rsa, 0, sizeof(*rsa));
00883         isc_mem_put(key->mctx, rsa, sizeof(*rsa));
00884         return (ISC_R_NOMEMORY);
00885 }
00886 
00887 static isc_result_t
00888 pkcs11rsa_tofile(const dst_key_t *key, const char *directory) {
00889         int i;
00890         pk11_object_t *rsa;
00891         CK_ATTRIBUTE *attr;
00892         CK_ATTRIBUTE *modulus = NULL, *exponent = NULL;
00893         CK_ATTRIBUTE  *d = NULL, *p = NULL, *q = NULL;
00894         CK_ATTRIBUTE *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL;
00895         dst_private_t priv;
00896         unsigned char *bufs[10];
00897         isc_result_t result;
00898 
00899         if (key->keydata.pkey == NULL)
00900                 return (DST_R_NULLKEY);
00901 
00902         if (key->external) {
00903                 priv.nelements = 0;
00904                 return (dst__privstruct_writefile(key, &priv, directory));
00905         }
00906 
00907         rsa = key->keydata.pkey;
00908 
00909         for (attr = pk11_attribute_first(rsa);
00910              attr != NULL;
00911              attr = pk11_attribute_next(rsa, attr))
00912                 switch (attr->type) {
00913                 case CKA_MODULUS:
00914                         modulus = attr;
00915                         break;
00916                 case CKA_PUBLIC_EXPONENT:
00917                         exponent = attr;
00918                         break;
00919                 case CKA_PRIVATE_EXPONENT:
00920                         d = attr;
00921                         break;
00922                 case CKA_PRIME_1:
00923                         p = attr;
00924                         break;
00925                 case CKA_PRIME_2:
00926                         q = attr;
00927                         break;
00928                 case CKA_EXPONENT_1:
00929                         dmp1 = attr;
00930                         break;
00931                 case CKA_EXPONENT_2:
00932                         dmq1 = attr;
00933                         break;
00934                 case CKA_COEFFICIENT:
00935                         iqmp = attr;
00936                         break;
00937                 }
00938         if ((modulus == NULL) || (exponent == NULL))
00939                 return (DST_R_NULLKEY);
00940 
00941         memset(bufs, 0, sizeof(bufs));
00942 
00943         for (i = 0; i < 10; i++) {
00944                 bufs[i] = isc_mem_get(key->mctx, modulus->ulValueLen);
00945                 if (bufs[i] == NULL) {
00946                         result = ISC_R_NOMEMORY;
00947                         goto fail;
00948                 }
00949                 memset(bufs[i], 0, modulus->ulValueLen);
00950         }
00951 
00952         i = 0;
00953 
00954         priv.elements[i].tag = TAG_RSA_MODULUS;
00955         priv.elements[i].length = (unsigned short) modulus->ulValueLen;
00956         memmove(bufs[i], modulus->pValue, modulus->ulValueLen);
00957         priv.elements[i].data = bufs[i];
00958         i++;
00959 
00960         priv.elements[i].tag = TAG_RSA_PUBLICEXPONENT;
00961         priv.elements[i].length = (unsigned short) exponent->ulValueLen;
00962         memmove(bufs[i], exponent->pValue, exponent->ulValueLen);
00963         priv.elements[i].data = bufs[i];
00964         i++;
00965 
00966         if (d != NULL) {
00967                 priv.elements[i].tag = TAG_RSA_PRIVATEEXPONENT;
00968                 priv.elements[i].length = (unsigned short) d->ulValueLen;
00969                 memmove(bufs[i], d->pValue, d->ulValueLen);
00970                 priv.elements[i].data = bufs[i];
00971                 i++;
00972         }
00973 
00974         if (p != NULL) {
00975                 priv.elements[i].tag = TAG_RSA_PRIME1;
00976                 priv.elements[i].length = (unsigned short) p->ulValueLen;
00977                 memmove(bufs[i], p->pValue, p->ulValueLen);
00978                 priv.elements[i].data = bufs[i];
00979                 i++;
00980         }
00981 
00982         if (q != NULL) {
00983                 priv.elements[i].tag = TAG_RSA_PRIME2;
00984                 priv.elements[i].length = (unsigned short) q->ulValueLen;
00985                 memmove(bufs[i], q->pValue, q->ulValueLen);
00986                 priv.elements[i].data = bufs[i];
00987                 i++;
00988         }
00989 
00990         if (dmp1 != NULL) {
00991                 priv.elements[i].tag = TAG_RSA_EXPONENT1;
00992                 priv.elements[i].length = (unsigned short) dmp1->ulValueLen;
00993                 memmove(bufs[i], dmp1->pValue, dmp1->ulValueLen);
00994                 priv.elements[i].data = bufs[i];
00995                 i++;
00996         }
00997 
00998         if (dmq1 != NULL) {
00999                 priv.elements[i].tag = TAG_RSA_EXPONENT2;
01000                 priv.elements[i].length = (unsigned short) dmq1->ulValueLen;
01001                 memmove(bufs[i], dmq1->pValue, dmq1->ulValueLen);
01002                 priv.elements[i].data = bufs[i];
01003                 i++;
01004         }
01005 
01006         if (iqmp != NULL) {
01007                 priv.elements[i].tag = TAG_RSA_COEFFICIENT;
01008                 priv.elements[i].length = (unsigned short) iqmp->ulValueLen;
01009                 memmove(bufs[i], iqmp->pValue, iqmp->ulValueLen);
01010                 priv.elements[i].data = bufs[i];
01011                 i++;
01012         }
01013 
01014         if (key->engine != NULL) {
01015                 priv.elements[i].tag = TAG_RSA_ENGINE;
01016                 priv.elements[i].length =
01017                         (unsigned short)strlen(key->engine) + 1;
01018                 priv.elements[i].data = (unsigned char *)key->engine;
01019                 i++;
01020         }
01021 
01022         if (key->label != NULL) {
01023                 priv.elements[i].tag = TAG_RSA_LABEL;
01024                 priv.elements[i].length =
01025                         (unsigned short)strlen(key->label) + 1;
01026                 priv.elements[i].data = (unsigned char *)key->label;
01027                 i++;
01028         }
01029 
01030         priv.nelements = i;
01031         result = dst__privstruct_writefile(key, &priv, directory);
01032  fail:
01033         for (i = 0; i < 10; i++) {
01034                 if (bufs[i] == NULL)
01035                         break;
01036                 memset(bufs[i], 0, modulus->ulValueLen);
01037                 isc_mem_put(key->mctx, bufs[i], modulus->ulValueLen);
01038         }
01039         return (result);
01040 }
01041 
01042 static isc_result_t
01043 pkcs11rsa_fetch(dst_key_t *key, const char *engine, const char *label,
01044                 dst_key_t *pub)
01045 {
01046         CK_RV rv;
01047         CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
01048         CK_KEY_TYPE keyType = CKK_RSA;
01049         CK_ATTRIBUTE searchTemplate[] =
01050         {
01051                 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
01052                 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
01053                 { CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) },
01054                 { CKA_LABEL, NULL, 0 }
01055         };
01056         CK_ULONG cnt;
01057         CK_ATTRIBUTE *attr;
01058         CK_ATTRIBUTE *pubattr;
01059         pk11_object_t *rsa;
01060         pk11_object_t *pubrsa;
01061         pk11_context_t *pk11_ctx = NULL;
01062         isc_result_t ret;
01063 
01064         if (label == NULL)
01065                 return (DST_R_NOENGINE);
01066 
01067         rsa = key->keydata.pkey;
01068         pubrsa = pub->keydata.pkey;
01069 
01070         rsa->object = CK_INVALID_HANDLE;
01071         rsa->ontoken = ISC_TRUE;
01072         rsa->reqlogon = ISC_TRUE;
01073         rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
01074         if (rsa->repr == NULL)
01075                 return (ISC_R_NOMEMORY);
01076         memset(rsa->repr, 0, sizeof(*attr) * 2);
01077         rsa->attrcnt = 2;
01078         attr = rsa->repr;
01079 
01080         attr->type = CKA_MODULUS;
01081         pubattr = pk11_attribute_bytype(pubrsa, CKA_MODULUS);
01082         attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen);
01083         if (attr->pValue == NULL)
01084                 DST_RET(ISC_R_NOMEMORY);
01085         memmove(attr->pValue, pubattr->pValue, pubattr->ulValueLen);
01086         attr->ulValueLen = pubattr->ulValueLen;
01087         attr++;
01088 
01089         attr->type = CKA_PUBLIC_EXPONENT;
01090         pubattr = pk11_attribute_bytype(pubrsa, CKA_PUBLIC_EXPONENT);
01091         attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen);
01092         if (attr->pValue == NULL)
01093                 DST_RET(ISC_R_NOMEMORY);
01094         memmove(attr->pValue, pubattr->pValue, pubattr->ulValueLen);
01095         attr->ulValueLen = pubattr->ulValueLen;
01096 
01097         ret = pk11_parse_uri(rsa, label, key->mctx, OP_RSA);
01098         if (ret != ISC_R_SUCCESS)
01099                 goto err;
01100 
01101         pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
01102                                                   sizeof(*pk11_ctx));
01103         if (pk11_ctx == NULL)
01104                 DST_RET(ISC_R_NOMEMORY);
01105         ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE,
01106                                rsa->reqlogon, NULL, rsa->slot);
01107         if (ret != ISC_R_SUCCESS)
01108                 goto err;
01109 
01110         attr = pk11_attribute_bytype(rsa, CKA_LABEL);
01111         if (attr == NULL) {
01112                 attr = pk11_attribute_bytype(rsa, CKA_ID);
01113                 INSIST(attr != NULL);
01114                 searchTemplate[3].type = CKA_ID;
01115         }
01116         searchTemplate[3].pValue = attr->pValue;
01117         searchTemplate[3].ulValueLen = attr->ulValueLen;
01118 
01119         PK11_RET(pkcs_C_FindObjectsInit,
01120                  (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
01121                  DST_R_CRYPTOFAILURE);
01122         PK11_RET(pkcs_C_FindObjects,
01123                  (pk11_ctx->session, &rsa->object, (CK_ULONG) 1, &cnt),
01124                  DST_R_CRYPTOFAILURE);
01125         (void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
01126         if (cnt == 0)
01127                 DST_RET(ISC_R_NOTFOUND);
01128         if (cnt > 1)
01129                 DST_RET(ISC_R_EXISTS);
01130 
01131         if (engine != NULL) {
01132                 key->engine = isc_mem_strdup(key->mctx, engine);
01133                 if (key->engine == NULL)
01134                         DST_RET(ISC_R_NOMEMORY);
01135         }
01136 
01137         key->label = isc_mem_strdup(key->mctx, label);
01138         if (key->label == NULL)
01139                 DST_RET(ISC_R_NOMEMORY);
01140 
01141         pk11_return_session(pk11_ctx);
01142         memset(pk11_ctx, 0, sizeof(*pk11_ctx));
01143         isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
01144 
01145         attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
01146         INSIST(attr != NULL);
01147         key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);
01148 
01149         return (ISC_R_SUCCESS);
01150 
01151     err:
01152         if (pk11_ctx != NULL) {
01153                 pk11_return_session(pk11_ctx);
01154                 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
01155                 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
01156         }
01157 
01158         return (ret);
01159 }
01160 
01161 static isc_result_t
01162 rsa_check(pk11_object_t *rsa, pk11_object_t *pubrsa) {
01163         CK_ATTRIBUTE *pubattr, *privattr;
01164         CK_BYTE *priv_exp = NULL, *priv_mod = NULL;
01165         CK_BYTE *pub_exp = NULL, *pub_mod = NULL;
01166         unsigned int priv_explen = 0, priv_modlen = 0;
01167         unsigned int pub_explen = 0, pub_modlen = 0;
01168 
01169         REQUIRE(rsa != NULL && pubrsa != NULL);
01170 
01171         privattr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT);
01172         INSIST(privattr != NULL);
01173         priv_exp = privattr->pValue;
01174         priv_explen = privattr->ulValueLen;
01175 
01176         pubattr = pk11_attribute_bytype(pubrsa, CKA_PUBLIC_EXPONENT);
01177         INSIST(pubattr != NULL);
01178         pub_exp = pubattr->pValue;
01179         pub_explen = pubattr->ulValueLen;
01180 
01181         if (priv_exp != NULL) {
01182                 if (priv_explen != pub_explen)
01183                         return (DST_R_INVALIDPRIVATEKEY);
01184                 if (memcmp(priv_exp, pub_exp, pub_explen) != 0)
01185                         return (DST_R_INVALIDPRIVATEKEY);
01186         } else {
01187                 privattr->pValue = pub_exp;
01188                 privattr->ulValueLen = pub_explen;
01189                 pubattr->pValue = NULL;
01190                 pubattr->ulValueLen = 0;
01191         }
01192 
01193         if (privattr->pValue == NULL)
01194                 return (DST_R_INVALIDPRIVATEKEY);
01195 
01196         privattr = pk11_attribute_bytype(rsa, CKA_MODULUS);
01197         INSIST(privattr != NULL);
01198         priv_mod = privattr->pValue;
01199         priv_modlen = privattr->ulValueLen;
01200 
01201         pubattr = pk11_attribute_bytype(pubrsa, CKA_MODULUS);
01202         INSIST(pubattr != NULL);
01203         pub_mod = pubattr->pValue;
01204         pub_modlen = pubattr->ulValueLen;
01205 
01206         if (priv_mod != NULL) {
01207                 if (priv_modlen != pub_modlen)
01208                         return (DST_R_INVALIDPRIVATEKEY);
01209                 if (memcmp(priv_mod, pub_mod, pub_modlen) != 0)
01210                         return (DST_R_INVALIDPRIVATEKEY);
01211         } else {
01212                 privattr->pValue = pub_mod;
01213                 privattr->ulValueLen = pub_modlen;
01214                 pubattr->pValue = NULL;
01215                 pubattr->ulValueLen = 0;
01216         }
01217 
01218         if (privattr->pValue == NULL)
01219                 return (DST_R_INVALIDPRIVATEKEY);
01220 
01221         return (ISC_R_SUCCESS);
01222 }
01223 
01224 static isc_result_t
01225 pkcs11rsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
01226         dst_private_t priv;
01227         isc_result_t ret;
01228         int i;
01229         pk11_object_t *rsa;
01230         CK_ATTRIBUTE *attr;
01231         isc_mem_t *mctx = key->mctx;
01232         const char *engine = NULL, *label = NULL;
01233 
01234         /* read private key file */
01235         ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv);
01236         if (ret != ISC_R_SUCCESS)
01237                 return (ret);
01238 
01239         if (key->external) {
01240                 if (priv.nelements != 0)
01241                         DST_RET(DST_R_INVALIDPRIVATEKEY);
01242                 if (pub == NULL)
01243                         DST_RET(DST_R_INVALIDPRIVATEKEY);
01244 
01245                 key->keydata.pkey = pub->keydata.pkey;
01246                 pub->keydata.pkey = NULL;
01247                 key->key_size = pub->key_size;
01248 
01249                 dst__privstruct_free(&priv, mctx);
01250                 memset(&priv, 0, sizeof(priv));
01251 
01252                 return (ISC_R_SUCCESS);
01253         }
01254 
01255         for (i = 0; i < priv.nelements; i++) {
01256                 switch (priv.elements[i].tag) {
01257                 case TAG_RSA_ENGINE:
01258                         engine = (char *)priv.elements[i].data;
01259                         break;
01260                 case TAG_RSA_LABEL:
01261                         label = (char *)priv.elements[i].data;
01262                         break;
01263                 default:
01264                         break;
01265                 }
01266         }
01267         rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa));
01268         if (rsa == NULL)
01269                 DST_RET(ISC_R_NOMEMORY);
01270         memset(rsa, 0, sizeof(*rsa));
01271         key->keydata.pkey = rsa;
01272 
01273         /* Is this key is stored in a HSM? See if we can fetch it. */
01274         if ((label != NULL) || (engine != NULL)) {
01275                 ret = pkcs11rsa_fetch(key, engine, label, pub);
01276                 if (ret != ISC_R_SUCCESS)
01277                         goto err;
01278                 dst__privstruct_free(&priv, mctx);
01279                 memset(&priv, 0, sizeof(priv));
01280                 return (ret);
01281         }
01282 
01283         rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 8);
01284         if (rsa->repr == NULL)
01285                 DST_RET(ISC_R_NOMEMORY);
01286         memset(rsa->repr, 0, sizeof(*attr) * 8);
01287         rsa->attrcnt = 8;
01288         attr = rsa->repr;
01289         attr[0].type = CKA_MODULUS;
01290         attr[1].type = CKA_PUBLIC_EXPONENT;
01291         attr[2].type = CKA_PRIVATE_EXPONENT;
01292         attr[3].type = CKA_PRIME_1;
01293         attr[4].type = CKA_PRIME_2;
01294         attr[5].type = CKA_EXPONENT_1;
01295         attr[6].type = CKA_EXPONENT_2;
01296         attr[7].type = CKA_COEFFICIENT;
01297 
01298         for (i = 0; i < priv.nelements; i++) {
01299                 CK_BYTE *bn;
01300 
01301                 switch (priv.elements[i].tag) {
01302                 case TAG_RSA_ENGINE:
01303                         continue;
01304                 case TAG_RSA_LABEL:
01305                         continue;
01306                 default:
01307                         bn = isc_mem_get(key->mctx, priv.elements[i].length);
01308                         if (bn == NULL)
01309                                 DST_RET(ISC_R_NOMEMORY);
01310                         memmove(bn, priv.elements[i].data,
01311                                 priv.elements[i].length);
01312                 }
01313 
01314                 switch (priv.elements[i].tag) {
01315                         case TAG_RSA_MODULUS:
01316                                 attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
01317                                 INSIST(attr != NULL);
01318                                 attr->pValue = bn;
01319                                 attr->ulValueLen = priv.elements[i].length;
01320                                 break;
01321                         case TAG_RSA_PUBLICEXPONENT:
01322                                 attr = pk11_attribute_bytype(rsa,
01323                                                 CKA_PUBLIC_EXPONENT);
01324                                 INSIST(attr != NULL);
01325                                 attr->pValue = bn;
01326                                 attr->ulValueLen = priv.elements[i].length;
01327                                 break;
01328                         case TAG_RSA_PRIVATEEXPONENT:
01329                                 attr = pk11_attribute_bytype(rsa,
01330                                                 CKA_PRIVATE_EXPONENT);
01331                                 INSIST(attr != NULL);
01332                                 attr->pValue = bn;
01333                                 attr->ulValueLen = priv.elements[i].length;
01334                                 break;
01335                         case TAG_RSA_PRIME1:
01336                                 attr = pk11_attribute_bytype(rsa, CKA_PRIME_1);
01337                                 INSIST(attr != NULL);
01338                                 attr->pValue = bn;
01339                                 attr->ulValueLen = priv.elements[i].length;
01340                                 break;
01341                         case TAG_RSA_PRIME2:
01342                                 attr = pk11_attribute_bytype(rsa, CKA_PRIME_2);
01343                                 INSIST(attr != NULL);
01344                                 attr->pValue = bn;
01345                                 attr->ulValueLen = priv.elements[i].length;
01346                                 break;
01347                         case TAG_RSA_EXPONENT1:
01348                                 attr = pk11_attribute_bytype(rsa,
01349                                                              CKA_EXPONENT_1);
01350                                 INSIST(attr != NULL);
01351                                 attr->pValue = bn;
01352                                 attr->ulValueLen = priv.elements[i].length;
01353                                 break;
01354                         case TAG_RSA_EXPONENT2:
01355                                 attr = pk11_attribute_bytype(rsa,
01356                                                              CKA_EXPONENT_2);
01357                                 INSIST(attr != NULL);
01358                                 attr->pValue = bn;
01359                                 attr->ulValueLen = priv.elements[i].length;
01360                                 break;
01361                         case TAG_RSA_COEFFICIENT:
01362                                 attr = pk11_attribute_bytype(rsa,
01363                                                              CKA_COEFFICIENT);
01364                                 INSIST(attr != NULL);
01365                                 attr->pValue = bn;
01366                                 attr->ulValueLen = priv.elements[i].length;
01367                                 break;
01368                 }
01369         }
01370 
01371         if (rsa_check(rsa, pub->keydata.pkey) != ISC_R_SUCCESS)
01372                 DST_RET(DST_R_INVALIDPRIVATEKEY);
01373 
01374         attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
01375         INSIST(attr != NULL);
01376         key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);
01377 
01378         attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT);
01379         INSIST(attr != NULL);
01380         if (pk11_numbits(attr->pValue, attr->ulValueLen) > RSA_MAX_PUBEXP_BITS)
01381                 DST_RET(ISC_R_RANGE);
01382 
01383         dst__privstruct_free(&priv, mctx);
01384         memset(&priv, 0, sizeof(priv));
01385 
01386         return (ISC_R_SUCCESS);
01387 
01388  err:
01389         pkcs11rsa_destroy(key);
01390         dst__privstruct_free(&priv, mctx);
01391         memset(&priv, 0, sizeof(priv));
01392         return (ret);
01393 }
01394 
01395 static isc_result_t
01396 pkcs11rsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
01397                     const char *pin)
01398 {
01399         CK_RV rv;
01400         CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
01401         CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
01402         CK_KEY_TYPE keyType = CKK_RSA;
01403         CK_ATTRIBUTE searchTemplate[] =
01404         {
01405                 { CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
01406                 { CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
01407                 { CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) },
01408                 { CKA_LABEL, NULL, 0 }
01409         };
01410         CK_ULONG cnt;
01411         CK_ATTRIBUTE *attr;
01412         pk11_object_t *rsa;
01413         pk11_context_t *pk11_ctx = NULL;
01414         isc_result_t ret;
01415         unsigned int i;
01416 
01417         UNUSED(pin);
01418 
01419         rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa));
01420         if (rsa == NULL)
01421                 return (ISC_R_NOMEMORY);
01422         memset(rsa, 0, sizeof(*rsa));
01423         rsa->object = CK_INVALID_HANDLE;
01424         rsa->ontoken = ISC_TRUE;
01425         rsa->reqlogon = ISC_TRUE;
01426         key->keydata.pkey = rsa;
01427 
01428         rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
01429         if (rsa->repr == NULL)
01430                 DST_RET(ISC_R_NOMEMORY);
01431         memset(rsa->repr, 0, sizeof(*attr) * 2);
01432         rsa->attrcnt = 2;
01433         attr = rsa->repr;
01434         attr[0].type = CKA_MODULUS;
01435         attr[1].type = CKA_PUBLIC_EXPONENT;
01436 
01437         ret = pk11_parse_uri(rsa, label, key->mctx, OP_RSA);
01438         if (ret != ISC_R_SUCCESS)
01439                 goto err;
01440 
01441         pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
01442                                                   sizeof(*pk11_ctx));
01443         if (pk11_ctx == NULL)
01444                 DST_RET(ISC_R_NOMEMORY);
01445         ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE,
01446                                rsa->reqlogon, NULL, rsa->slot);
01447         if (ret != ISC_R_SUCCESS)
01448                 goto err;
01449 
01450         attr = pk11_attribute_bytype(rsa, CKA_LABEL);
01451         if (attr == NULL) {
01452                 attr = pk11_attribute_bytype(rsa, CKA_ID);
01453                 INSIST(attr != NULL);
01454                 searchTemplate[3].type = CKA_ID;
01455         }
01456         searchTemplate[3].pValue = attr->pValue;
01457         searchTemplate[3].ulValueLen = attr->ulValueLen;
01458 
01459         PK11_RET(pkcs_C_FindObjectsInit,
01460                  (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
01461                  DST_R_CRYPTOFAILURE);
01462         PK11_RET(pkcs_C_FindObjects,
01463                  (pk11_ctx->session, &hKey, (CK_ULONG) 1, &cnt),
01464                  DST_R_CRYPTOFAILURE);
01465         (void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
01466         if (cnt == 0)
01467                 DST_RET(ISC_R_NOTFOUND);
01468         if (cnt > 1)
01469                 DST_RET(ISC_R_EXISTS);
01470 
01471         attr = rsa->repr;
01472         PK11_RET(pkcs_C_GetAttributeValue,
01473                  (pk11_ctx->session, hKey, attr, 2),
01474                  DST_R_CRYPTOFAILURE);
01475         for (i = 0; i <= 1; i++) {
01476                 attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen);
01477                 if (attr[i].pValue == NULL)
01478                         DST_RET(ISC_R_NOMEMORY);
01479                 memset(attr[i].pValue, 0, attr[i].ulValueLen);
01480         }
01481         PK11_RET(pkcs_C_GetAttributeValue,
01482                  (pk11_ctx->session, hKey, attr, 2),
01483                  DST_R_CRYPTOFAILURE);
01484 
01485         keyClass = CKO_PRIVATE_KEY;
01486         PK11_RET(pkcs_C_FindObjectsInit,
01487                  (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
01488                  DST_R_CRYPTOFAILURE);
01489         PK11_RET(pkcs_C_FindObjects,
01490                  (pk11_ctx->session, &rsa->object, (CK_ULONG) 1, &cnt),
01491                  DST_R_CRYPTOFAILURE);
01492         (void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
01493         if (cnt == 0)
01494                 DST_RET(ISC_R_NOTFOUND);
01495         if (cnt > 1)
01496                 DST_RET(ISC_R_EXISTS);
01497 
01498         if (engine != NULL) {
01499                 key->engine = isc_mem_strdup(key->mctx, engine);
01500                 if (key->engine == NULL)
01501                         DST_RET(ISC_R_NOMEMORY);
01502         }
01503 
01504         key->label = isc_mem_strdup(key->mctx, label);
01505         if (key->label == NULL)
01506                 DST_RET(ISC_R_NOMEMORY);
01507 
01508         attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT);
01509         INSIST(attr != NULL);
01510         if (pk11_numbits(attr->pValue, attr->ulValueLen) > RSA_MAX_PUBEXP_BITS)
01511                 DST_RET(ISC_R_RANGE);
01512 
01513         attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
01514         INSIST(attr != NULL);
01515         key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);
01516 
01517         pk11_return_session(pk11_ctx);
01518         memset(pk11_ctx, 0, sizeof(*pk11_ctx));
01519         isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
01520 
01521         return (ISC_R_SUCCESS);
01522 
01523     err:
01524         pkcs11rsa_destroy(key);
01525         if (pk11_ctx != NULL) {
01526                 pk11_return_session(pk11_ctx);
01527                 memset(pk11_ctx, 0, sizeof(*pk11_ctx));
01528                 isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
01529         }
01530 
01531         return (ret);
01532 }
01533 
01534 static dst_func_t pkcs11rsa_functions = {
01535         pkcs11rsa_createctx,
01536         pkcs11rsa_createctx2,
01537         pkcs11rsa_destroyctx,
01538         pkcs11rsa_adddata,
01539         pkcs11rsa_sign,
01540         pkcs11rsa_verify,
01541         NULL, /*%< verify2 */
01542         NULL, /*%< computesecret */
01543         pkcs11rsa_compare,
01544         NULL, /*%< paramcompare */
01545         pkcs11rsa_generate,
01546         pkcs11rsa_isprivate,
01547         pkcs11rsa_destroy,
01548         pkcs11rsa_todns,
01549         pkcs11rsa_fromdns,
01550         pkcs11rsa_tofile,
01551         pkcs11rsa_parse,
01552         NULL, /*%< cleanup */
01553         pkcs11rsa_fromlabel,
01554         NULL, /*%< dump */
01555         NULL, /*%< restore */
01556 };
01557 
01558 isc_result_t
01559 dst__pkcs11rsa_init(dst_func_t **funcp) {
01560         REQUIRE(funcp != NULL);
01561 
01562         if (*funcp == NULL)
01563                 *funcp = &pkcs11rsa_functions;
01564         return (ISC_R_SUCCESS);
01565 }
01566 
01567 #else /* PKCS11CRYPTO */
01568 
01569 #include <isc/util.h>
01570 
01571 EMPTY_TRANSLATION_UNIT
01572 
01573 #endif /* PKCS11CRYPTO */
01574 /*! \file */

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