00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <config.h>
00020
00021 #if defined(OPENSSL) && defined(HAVE_OPENSSL_GOST)
00022
00023 #include <isc/entropy.h>
00024 #include <isc/mem.h>
00025 #include <isc/string.h>
00026 #include <isc/util.h>
00027
00028 #include <dst/result.h>
00029
00030 #include "dst_internal.h"
00031 #include "dst_openssl.h"
00032 #include "dst_parse.h"
00033 #include "dst_gost.h"
00034
00035 #include <openssl/err.h>
00036 #include <openssl/objects.h>
00037 #include <openssl/rsa.h>
00038 #include <openssl/engine.h>
00039
00040 static ENGINE *e = NULL;
00041 static const EVP_MD *opensslgost_digest;
00042 extern const EVP_MD *EVP_gost(void);
00043
00044 const EVP_MD *EVP_gost(void) {
00045 return (opensslgost_digest);
00046 }
00047
00048
00049
00050 isc_result_t
00051 isc_gost_init(isc_gost_t *ctx) {
00052 const EVP_MD *md;
00053 int ret;
00054
00055 INSIST(ctx != NULL);
00056
00057 md = EVP_gost();
00058 if (md == NULL)
00059 return (DST_R_CRYPTOFAILURE);
00060 EVP_MD_CTX_init(ctx);
00061 ret = EVP_DigestInit(ctx, md);
00062 if (ret != 1)
00063 return (DST_R_CRYPTOFAILURE);
00064 return (ISC_R_SUCCESS);
00065 }
00066
00067 void
00068 isc_gost_invalidate(isc_gost_t *ctx) {
00069 EVP_MD_CTX_cleanup(ctx);
00070 }
00071
00072 isc_result_t
00073 isc_gost_update(isc_gost_t *ctx, const unsigned char *data,
00074 unsigned int len)
00075 {
00076 int ret;
00077
00078 INSIST(ctx != NULL);
00079 INSIST(data != NULL);
00080
00081 ret = EVP_DigestUpdate(ctx, (const void *) data, (size_t) len);
00082 if (ret != 1)
00083 return (DST_R_CRYPTOFAILURE);
00084 return (ISC_R_SUCCESS);
00085 }
00086
00087 isc_result_t
00088 isc_gost_final(isc_gost_t *ctx, unsigned char *digest) {
00089 int ret;
00090
00091 INSIST(ctx != NULL);
00092 INSIST(digest != NULL);
00093
00094 ret = EVP_DigestFinal(ctx, digest, NULL);
00095 if (ret != 1)
00096 return (DST_R_CRYPTOFAILURE);
00097 return (ISC_R_SUCCESS);
00098 }
00099
00100
00101
00102 #define DST_RET(a) {ret = a; goto err;}
00103
00104 static isc_result_t opensslgost_todns(const dst_key_t *key,
00105 isc_buffer_t *data);
00106
00107 static isc_result_t
00108 opensslgost_createctx(dst_key_t *key, dst_context_t *dctx) {
00109 EVP_MD_CTX *evp_md_ctx;
00110 const EVP_MD *md = EVP_gost();
00111
00112 UNUSED(key);
00113
00114 if (md == NULL)
00115 return (DST_R_OPENSSLFAILURE);
00116
00117 evp_md_ctx = EVP_MD_CTX_create();
00118 if (evp_md_ctx == NULL)
00119 return (ISC_R_NOMEMORY);
00120
00121 if (!EVP_DigestInit_ex(evp_md_ctx, md, NULL)) {
00122 EVP_MD_CTX_destroy(evp_md_ctx);
00123 return (ISC_R_FAILURE);
00124 }
00125 dctx->ctxdata.evp_md_ctx = evp_md_ctx;
00126
00127 return (ISC_R_SUCCESS);
00128 }
00129
00130 static void
00131 opensslgost_destroyctx(dst_context_t *dctx) {
00132 EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
00133
00134 if (evp_md_ctx != NULL) {
00135 EVP_MD_CTX_destroy(evp_md_ctx);
00136 dctx->ctxdata.evp_md_ctx = NULL;
00137 }
00138 }
00139
00140 static isc_result_t
00141 opensslgost_adddata(dst_context_t *dctx, const isc_region_t *data) {
00142 EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
00143
00144 if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length))
00145 return (ISC_R_FAILURE);
00146
00147 return (ISC_R_SUCCESS);
00148 }
00149
00150 static isc_result_t
00151 opensslgost_sign(dst_context_t *dctx, isc_buffer_t *sig) {
00152 dst_key_t *key = dctx->key;
00153 isc_region_t r;
00154 unsigned int siglen = 0;
00155 EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
00156 EVP_PKEY *pkey = key->keydata.pkey;
00157
00158 isc_buffer_availableregion(sig, &r);
00159
00160 if (r.length < (unsigned int) EVP_PKEY_size(pkey))
00161 return (ISC_R_NOSPACE);
00162
00163 if (!EVP_SignFinal(evp_md_ctx, r.base, &siglen, pkey))
00164 return (ISC_R_FAILURE);
00165
00166 isc_buffer_add(sig, siglen);
00167
00168 return (ISC_R_SUCCESS);
00169 }
00170
00171 static isc_result_t
00172 opensslgost_verify(dst_context_t *dctx, const isc_region_t *sig) {
00173 dst_key_t *key = dctx->key;
00174 int status = 0;
00175 EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
00176 EVP_PKEY *pkey = key->keydata.pkey;
00177
00178 status = EVP_VerifyFinal(evp_md_ctx, sig->base, sig->length, pkey);
00179 switch (status) {
00180 case 1:
00181 return (ISC_R_SUCCESS);
00182 case 0:
00183 return (dst__openssl_toresult(DST_R_VERIFYFAILURE));
00184 default:
00185 return (dst__openssl_toresult3(dctx->category,
00186 "EVP_VerifyFinal",
00187 DST_R_VERIFYFAILURE));
00188 }
00189 }
00190
00191 static isc_boolean_t
00192 opensslgost_compare(const dst_key_t *key1, const dst_key_t *key2) {
00193 EVP_PKEY *pkey1, *pkey2;
00194
00195 pkey1 = key1->keydata.pkey;
00196 pkey2 = key2->keydata.pkey;
00197
00198 if (pkey1 == NULL && pkey2 == NULL)
00199 return (ISC_TRUE);
00200 else if (pkey1 == NULL || pkey2 == NULL)
00201 return (ISC_FALSE);
00202
00203 if (EVP_PKEY_cmp(pkey1, pkey2) != 1)
00204 return (ISC_FALSE);
00205 return (ISC_TRUE);
00206 }
00207
00208 static int
00209 progress_cb(EVP_PKEY_CTX *ctx)
00210 {
00211 union {
00212 void *dptr;
00213 void (*fptr)(int);
00214 } u;
00215 int p;
00216
00217 u.dptr = EVP_PKEY_CTX_get_app_data(ctx);
00218 p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
00219 if (u.fptr != NULL)
00220 u.fptr(p);
00221 return (1);
00222 }
00223
00224 static isc_result_t
00225 opensslgost_generate(dst_key_t *key, int unused, void (*callback)(int)) {
00226 EVP_PKEY_CTX *ctx;
00227 union {
00228 void *dptr;
00229 void (*fptr)(int);
00230 } u;
00231 EVP_PKEY *pkey = NULL;
00232 isc_result_t ret;
00233
00234 UNUSED(unused);
00235 ctx = EVP_PKEY_CTX_new_id(NID_id_GostR3410_2001, NULL);
00236 if (ctx == NULL)
00237 DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_new_id",
00238 DST_R_OPENSSLFAILURE));
00239 if (callback != NULL) {
00240 u.fptr = callback;
00241 EVP_PKEY_CTX_set_app_data(ctx, u.dptr);
00242 EVP_PKEY_CTX_set_cb(ctx, &progress_cb);
00243 }
00244 if (EVP_PKEY_keygen_init(ctx) <= 0)
00245 DST_RET(dst__openssl_toresult2("EVP_PKEY_keygen_init",
00246 DST_R_OPENSSLFAILURE));
00247 if (EVP_PKEY_CTX_ctrl_str(ctx, "paramset", "A") <= 0)
00248 DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_ctrl_str",
00249 DST_R_OPENSSLFAILURE));
00250 if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
00251 DST_RET(dst__openssl_toresult2("EVP_PKEY_keygen",
00252 DST_R_OPENSSLFAILURE));
00253 key->keydata.pkey = pkey;
00254 key->key_size = EVP_PKEY_bits(pkey);
00255 EVP_PKEY_CTX_free(ctx);
00256 return (ISC_R_SUCCESS);
00257
00258 err:
00259 if (pkey != NULL)
00260 EVP_PKEY_free(pkey);
00261 if (ctx != NULL)
00262 EVP_PKEY_CTX_free(ctx);
00263 return (ret);
00264 }
00265
00266 static isc_boolean_t
00267 opensslgost_isprivate(const dst_key_t *key) {
00268 EVP_PKEY *pkey = key->keydata.pkey;
00269 EC_KEY *ec;
00270
00271 INSIST(pkey != NULL);
00272
00273 ec = EVP_PKEY_get0(pkey);
00274 return (ISC_TF(ec != NULL && EC_KEY_get0_private_key(ec) != NULL));
00275 }
00276
00277 static void
00278 opensslgost_destroy(dst_key_t *key) {
00279 EVP_PKEY *pkey = key->keydata.pkey;
00280
00281 EVP_PKEY_free(pkey);
00282 key->keydata.pkey = NULL;
00283 }
00284
00285 unsigned char gost_prefix[37] = {
00286 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
00287 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07,
00288 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01, 0x06,
00289 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x1e, 0x01,
00290 0x03, 0x43, 0x00, 0x04, 0x40
00291 };
00292
00293 static isc_result_t
00294 opensslgost_todns(const dst_key_t *key, isc_buffer_t *data) {
00295 EVP_PKEY *pkey;
00296 isc_region_t r;
00297 unsigned char der[37 + 64], *p;
00298 int len;
00299
00300 REQUIRE(key->keydata.pkey != NULL);
00301
00302 pkey = key->keydata.pkey;
00303
00304 isc_buffer_availableregion(data, &r);
00305 if (r.length < 64)
00306 return (ISC_R_NOSPACE);
00307
00308 p = der;
00309 len = i2d_PUBKEY(pkey, &p);
00310 INSIST(len == sizeof(der));
00311 INSIST(memcmp(gost_prefix, der, 37) == 0);
00312 memmove(r.base, der + 37, 64);
00313 isc_buffer_add(data, 64);
00314
00315 return (ISC_R_SUCCESS);
00316 }
00317
00318 static isc_result_t
00319 opensslgost_fromdns(dst_key_t *key, isc_buffer_t *data) {
00320 isc_region_t r;
00321 EVP_PKEY *pkey = NULL;
00322 unsigned char der[37 + 64];
00323 const unsigned char *p;
00324
00325 isc_buffer_remainingregion(data, &r);
00326 if (r.length == 0)
00327 return (ISC_R_SUCCESS);
00328
00329 if (r.length != 64)
00330 return (DST_R_INVALIDPUBLICKEY);
00331 memmove(der, gost_prefix, 37);
00332 memmove(der + 37, r.base, 64);
00333 isc_buffer_forward(data, 64);
00334
00335 p = der;
00336 if (d2i_PUBKEY(&pkey, &p, (long) sizeof(der)) == NULL)
00337 return (dst__openssl_toresult2("d2i_PUBKEY",
00338 DST_R_OPENSSLFAILURE));
00339 key->keydata.pkey = pkey;
00340 key->key_size = EVP_PKEY_bits(pkey);
00341
00342 return (ISC_R_SUCCESS);
00343 }
00344
00345 #ifdef PREFER_GOSTASN1
00346
00347 static isc_result_t
00348 opensslgost_tofile(const dst_key_t *key, const char *directory) {
00349 EVP_PKEY *pkey;
00350 dst_private_t priv;
00351 isc_result_t result;
00352 unsigned char *der, *p;
00353 int len;
00354
00355 if (key->keydata.pkey == NULL)
00356 return (DST_R_NULLKEY);
00357
00358 if (key->external) {
00359 priv.nelements = 0;
00360 return (dst__privstruct_writefile(key, &priv, directory));
00361 }
00362
00363 pkey = key->keydata.pkey;
00364
00365 len = i2d_PrivateKey(pkey, NULL);
00366 der = isc_mem_get(key->mctx, (size_t) len);
00367 if (der == NULL)
00368 return (ISC_R_NOMEMORY);
00369
00370 p = der;
00371 if (i2d_PrivateKey(pkey, &p) != len) {
00372 result = dst__openssl_toresult2("i2d_PrivateKey",
00373 DST_R_OPENSSLFAILURE);
00374 goto fail;
00375 }
00376
00377 priv.elements[0].tag = TAG_GOST_PRIVASN1;
00378 priv.elements[0].length = len;
00379 priv.elements[0].data = der;
00380 priv.nelements = 1;
00381
00382 result = dst__privstruct_writefile(key, &priv, directory);
00383 fail:
00384 if (der != NULL)
00385 isc_mem_put(key->mctx, der, (size_t) len);
00386 return (result);
00387 }
00388
00389 #else
00390
00391 static isc_result_t
00392 opensslgost_tofile(const dst_key_t *key, const char *directory) {
00393 EVP_PKEY *pkey;
00394 EC_KEY *eckey;
00395 const BIGNUM *privkey;
00396 dst_private_t priv;
00397 isc_result_t ret;
00398 unsigned char *buf = NULL;
00399
00400 if (key->keydata.pkey == NULL)
00401 return (DST_R_NULLKEY);
00402
00403 if (key->external) {
00404 priv.nelements = 0;
00405 return (dst__privstruct_writefile(key, &priv, directory));
00406 }
00407
00408 pkey = key->keydata.pkey;
00409 eckey = EVP_PKEY_get0(pkey);
00410 if (eckey == NULL)
00411 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
00412 privkey = EC_KEY_get0_private_key(eckey);
00413 if (privkey == NULL)
00414 return (ISC_R_FAILURE);
00415
00416 buf = isc_mem_get(key->mctx, BN_num_bytes(privkey));
00417 if (buf == NULL)
00418 return (ISC_R_NOMEMORY);
00419
00420 priv.elements[0].tag = TAG_GOST_PRIVRAW;
00421 priv.elements[0].length = BN_num_bytes(privkey);
00422 BN_bn2bin(privkey, buf);
00423 priv.elements[0].data = buf;
00424 priv.nelements = 1;
00425
00426 ret = dst__privstruct_writefile(key, &priv, directory);
00427
00428 if (buf != NULL)
00429 isc_mem_put(key->mctx, buf, BN_num_bytes(privkey));
00430 return (ret);
00431 }
00432 #endif
00433
00434 static unsigned char gost_dummy_key[71] = {
00435 0x30, 0x45, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x06,
00436 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x13, 0x30,
00437 0x12, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02,
00438 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02,
00439 0x02, 0x1e, 0x01, 0x04, 0x22, 0x02, 0x20, 0x1b,
00440 0x3f, 0x94, 0xf7, 0x1a, 0x5f, 0x2f, 0xe7, 0xe5,
00441 0x74, 0x0b, 0x8c, 0xd4, 0xb7, 0x18, 0xdd, 0x65,
00442 0x68, 0x26, 0xd1, 0x54, 0xfb, 0x77, 0xba, 0x63,
00443 0x72, 0xd9, 0xf0, 0x63, 0x87, 0xe0, 0xd6
00444 };
00445
00446 static isc_result_t
00447 opensslgost_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
00448 dst_private_t priv;
00449 isc_result_t ret;
00450 isc_mem_t *mctx = key->mctx;
00451 EVP_PKEY *pkey = NULL;
00452 EC_KEY *eckey;
00453 const EC_POINT *pubkey = NULL;
00454 BIGNUM *privkey = NULL;
00455 const unsigned char *p;
00456
00457
00458 ret = dst__privstruct_parse(key, DST_ALG_ECCGOST, lexer, mctx, &priv);
00459 if (ret != ISC_R_SUCCESS)
00460 return (ret);
00461
00462 if (key->external) {
00463 if (priv.nelements != 0)
00464 DST_RET(DST_R_INVALIDPRIVATEKEY);
00465 if (pub == NULL)
00466 DST_RET(DST_R_INVALIDPRIVATEKEY);
00467 key->keydata.pkey = pub->keydata.pkey;
00468 pub->keydata.pkey = NULL;
00469 key->key_size = pub->key_size;
00470 dst__privstruct_free(&priv, mctx);
00471 memset(&priv, 0, sizeof(priv));
00472 return (ISC_R_SUCCESS);
00473 }
00474
00475 INSIST((priv.elements[0].tag == TAG_GOST_PRIVASN1) ||
00476 (priv.elements[0].tag == TAG_GOST_PRIVRAW));
00477
00478 if (priv.elements[0].tag == TAG_GOST_PRIVASN1) {
00479 p = priv.elements[0].data;
00480 if (d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p,
00481 (long) priv.elements[0].length) == NULL)
00482 DST_RET(dst__openssl_toresult2(
00483 "d2i_PrivateKey",
00484 DST_R_INVALIDPRIVATEKEY));
00485 } else {
00486 if ((pub != NULL) && (pub->keydata.pkey != NULL)) {
00487 eckey = EVP_PKEY_get0(pub->keydata.pkey);
00488 pubkey = EC_KEY_get0_public_key(eckey);
00489 }
00490
00491 privkey = BN_bin2bn(priv.elements[0].data,
00492 priv.elements[0].length, NULL);
00493 if (privkey == NULL)
00494 DST_RET(ISC_R_NOMEMORY);
00495
00496
00497 p = gost_dummy_key;
00498 if (d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p,
00499 (long) sizeof(gost_dummy_key)) == NULL)
00500 DST_RET(dst__openssl_toresult2(
00501 "d2i_PrivateKey",
00502 DST_R_INVALIDPRIVATEKEY));
00503
00504 eckey = EVP_PKEY_get0(pkey);
00505 if (eckey == NULL)
00506 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
00507 if (!EC_KEY_set_private_key(eckey, privkey))
00508 DST_RET(ISC_R_NOMEMORY);
00509
00510
00511 #ifdef notyet
00512 (void) gost2001_compute_public(eckey);
00513 #else
00514 if ((pubkey != NULL) && !EC_KEY_set_public_key(eckey, pubkey))
00515 DST_RET(ISC_R_NOMEMORY);
00516 #endif
00517 BN_clear_free(privkey);
00518 privkey = NULL;
00519 }
00520 key->keydata.pkey = pkey;
00521 key->key_size = EVP_PKEY_bits(pkey);
00522 dst__privstruct_free(&priv, mctx);
00523 memset(&priv, 0, sizeof(priv));
00524 return (ISC_R_SUCCESS);
00525
00526 err:
00527 if (privkey != NULL)
00528 BN_clear_free(privkey);
00529 if (pkey != NULL)
00530 EVP_PKEY_free(pkey);
00531 opensslgost_destroy(key);
00532 dst__privstruct_free(&priv, mctx);
00533 memset(&priv, 0, sizeof(priv));
00534 return (ret);
00535 }
00536
00537 static void
00538 opensslgost_cleanup(void) {
00539 if (e != NULL) {
00540 ENGINE_finish(e);
00541 ENGINE_free(e);
00542 e = NULL;
00543 }
00544 }
00545
00546 static dst_func_t opensslgost_functions = {
00547 opensslgost_createctx,
00548 NULL,
00549 opensslgost_destroyctx,
00550 opensslgost_adddata,
00551 opensslgost_sign,
00552 opensslgost_verify,
00553 NULL,
00554 NULL,
00555 opensslgost_compare,
00556 NULL,
00557 opensslgost_generate,
00558 opensslgost_isprivate,
00559 opensslgost_destroy,
00560 opensslgost_todns,
00561 opensslgost_fromdns,
00562 opensslgost_tofile,
00563 opensslgost_parse,
00564 opensslgost_cleanup,
00565 NULL,
00566 NULL,
00567 NULL
00568 };
00569
00570 isc_result_t
00571 dst__opensslgost_init(dst_func_t **funcp) {
00572 isc_result_t ret;
00573
00574 REQUIRE(funcp != NULL);
00575
00576
00577 e = ENGINE_by_id("gost");
00578 if (e == NULL)
00579 return (dst__openssl_toresult2("ENGINE_by_id",
00580 DST_R_OPENSSLFAILURE));
00581 if (ENGINE_init(e) <= 0) {
00582 ENGINE_free(e);
00583 e = NULL;
00584 return (dst__openssl_toresult2("ENGINE_init",
00585 DST_R_OPENSSLFAILURE));
00586 }
00587
00588 opensslgost_digest = ENGINE_get_digest(e, NID_id_GostR3411_94);
00589 if (opensslgost_digest == NULL)
00590 DST_RET(dst__openssl_toresult2("ENGINE_get_digest",
00591 DST_R_OPENSSLFAILURE));
00592
00593 if (ENGINE_register_pkey_asn1_meths(e) <= 0)
00594 DST_RET(dst__openssl_toresult2(
00595 "ENGINE_register_pkey_asn1_meths",
00596 DST_R_OPENSSLFAILURE));
00597 if (ENGINE_ctrl_cmd_string(e,
00598 "CRYPT_PARAMS",
00599 "id-Gost28147-89-CryptoPro-A-ParamSet",
00600 0) <= 0)
00601 DST_RET(dst__openssl_toresult2("ENGINE_ctrl_cmd_string",
00602 DST_R_OPENSSLFAILURE));
00603
00604 if (*funcp == NULL)
00605 *funcp = &opensslgost_functions;
00606 return (ISC_R_SUCCESS);
00607
00608 err:
00609 ENGINE_finish(e);
00610 ENGINE_free(e);
00611 e = NULL;
00612 return (ret);
00613 }
00614
00615 #else
00616
00617 #include <isc/util.h>
00618
00619 EMPTY_TRANSLATION_UNIT
00620
00621 #endif
00622