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