1 /** 2 * OpenSSL Engine 3 * 4 * Copyright: 5 * (C) 1999-2007 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 8 * License: 9 * Botan is released under the Simplified BSD License (see LICENSE.md) 10 */ 11 module botan.engine.openssl_engine; 12 13 import botan.constants; 14 static if (BOTAN_HAS_ENGINE_OPENSSL): 15 16 import botan.engine.engine; 17 import botan.pubkey.pk_keys; 18 import botan.rng.rng; 19 import botan.block.block_cipher; 20 import botan.math.bigint.bigint; 21 import botan.utils.parsing; 22 import deimos.openssl.rc4; 23 import deimos.openssl.evp; 24 import deimos.openssl.bn; 25 import deimos.openssl.aes; 26 27 static if (BOTAN_HAS_RSA) import botan.pubkey.algo.rsa; 28 static if (BOTAN_HAS_DSA) import botan.pubkey.algo.dsa; 29 static if (BOTAN_HAS_ECDSA) { 30 import botan.pubkey.algo.ecdsa; 31 } 32 static if (BOTAN_HAS_DIFFIE_HELLMAN) import botan.pubkey.algo.dh; 33 34 /** 35 * OpenSSL Engine 36 */ 37 final class OpenSSLEngine : Engine 38 { 39 public: 40 string providerName() const { return "openssl"; } 41 42 KeyAgreement getKeyAgreementOp(in PrivateKey key, RandomNumberGenerator) const 43 { 44 static if (BOTAN_HAS_DIFFIE_HELLMAN) { 45 if (DHPrivateKey.algoName == key.algoName) 46 return new OSSLDHKAOperation(key); 47 } 48 49 return null; 50 } 51 52 Signature getSignatureOp(in PrivateKey key, RandomNumberGenerator) const 53 { 54 static if (BOTAN_HAS_RSA) { 55 if (RSAPrivateKey.algoName == key.algoName) 56 return new OSSLRSAPrivateOperation(key); 57 } 58 59 static if (BOTAN_HAS_DSA) { 60 if (DSAPrivateKey.algoName == key.algoName) 61 return new OSSLDSASignatureOperation(key); 62 } 63 64 return null; 65 } 66 67 Verification getVerifyOp(in PublicKey key, RandomNumberGenerator) const 68 { 69 static if (BOTAN_HAS_RSA) { 70 if (RSAPublicKey.algoName == key.algoName) 71 return new OSSLRSAPublicOperation(key); 72 } 73 74 static if (BOTAN_HAS_DSA) { 75 if (DSAPublicKey.algoName == key.algoName) 76 return new OSSLDSAVerificationOperation(key); 77 } 78 79 return null; 80 } 81 82 Encryption getEncryptionOp(in PublicKey key, RandomNumberGenerator) const 83 { 84 static if (BOTAN_HAS_RSA) { 85 if (RSAPublicKey.algoName == key.algoName) 86 return new OSSLRSAPublicOperation(key); 87 } 88 89 return null; 90 } 91 92 Decryption getDecryptionOp(in PrivateKey key, RandomNumberGenerator) const 93 { 94 static if (BOTAN_HAS_RSA) { 95 if (RSAPrivateKey.algoName == key.algoName) 96 return new OSSLRSAPrivateOperation(key); 97 } 98 99 return null; 100 } 101 102 /* 103 * Return the OpenSSL-based modular exponentiator 104 */ 105 ModularExponentiator modExp(const(BigInt)* n, PowerMod.UsageHints) const 106 { 107 return new OpenSSLModularExponentiator(*n); 108 } 109 110 111 /* 112 * Look for an algorithm with this name 113 */ 114 BlockCipher findBlockCipher(in SCANToken request, AlgorithmFactory af) const 115 { 116 117 static if (!BOTAN_HAS_OPENSSL_NO_SHA) { 118 /* 119 Using OpenSSL's AES causes crashes inside EVP on x86-64 with OpenSSL 0.9.8g 120 cause is unknown 121 */ 122 //mixin(HANDLE_EVP_CIPHER!("AES-128", EVP_aes_128_ecb)); 123 //mixin(HANDLE_EVP_CIPHER!("AES-192", EVP_aes_192_ecb)); 124 //mixin(HANDLE_EVP_CIPHER!("AES-256", EVP_aes_256_ecb)); 125 } 126 127 static if (!BOTAN_HAS_OPENSSL_NO_DES) { 128 mixin(HANDLE_EVP_CIPHER!("DES", EVP_des_ecb)); 129 mixin(HANDLE_EVP_CIPHER_KEYLEN!("TripleDES", EVP_des_ede3_ecb, 16, 24, 8)); 130 } 131 132 static if (!BOTAN_HAS_OPENSSL_NO_BF) { 133 mixin(HANDLE_EVP_CIPHER_KEYLEN!("Blowfish", EVP_bf_ecb, 1, 56, 1)); 134 } 135 136 static if (!BOTAN_HAS_OPENSSL_NO_CAST) { 137 mixin(HANDLE_EVP_CIPHER_KEYLEN!("Cast-128", EVP_cast5_ecb, 1, 16, 1)); 138 } 139 140 static if (!BOTAN_HAS_OPENSSL_NO_CAMELLIA) { 141 mixin(HANDLE_EVP_CIPHER!("Camellia-128", EVP_camellia_128_ecb)); 142 mixin(HANDLE_EVP_CIPHER!("Camellia-192", EVP_camellia_192_ecb)); 143 mixin(HANDLE_EVP_CIPHER!("Camellia-256", EVP_camellia_256_ecb)); 144 } 145 146 static if (!BOTAN_HAS_OPENSSL_NO_RC2) { 147 mixin(HANDLE_EVP_CIPHER_KEYLEN!("RC2", EVP_rc2_ecb, 1, 32, 1)); 148 } 149 150 static if (!BOTAN_HAS_OPENSSL_NO_RC5) { 151 /* 152 if (request.algoName == "RC5") 153 if (request.argAsInteger(0, 12) == 12) 154 return new EVP_BlockCipher(EVP_rc5_32_12_16_ecb, 155 "RC5(12)", 1, 32, 1); 156 */ 157 } 158 159 static if (!BOTAN_HAS_OPENSSL_NO_IDEA) { 160 // HANDLE_EVP_CIPHER!("IDEA", EVP_idea_ecb); 161 } 162 163 static if (!BOTAN_HAS_OPENSSL_NO_SEED) { 164 mixin(HANDLE_EVP_CIPHER!("SEED", EVP_seed_ecb)); 165 } 166 167 return null; 168 } 169 170 /** 171 * Look for an OpenSSL-supported stream cipher (RC4) 172 */ 173 StreamCipher findStreamCipher(in SCANToken request, 174 AlgorithmFactory) const 175 { 176 if (request.algoName == "RC4") 177 return new RC4OpenSSL(request.argAsInteger(0, 0)); 178 if (request.algoName == "RC4_drop") 179 return new RC4OpenSSL(768); 180 181 return null; 182 } 183 184 185 /* 186 * Look for an algorithm with this name 187 */ 188 HashFunction findHash(in SCANToken request, 189 AlgorithmFactory af) const 190 { 191 static if (!BOTAN_HAS_OPENSSL_NO_SHA) { 192 if (request.algoName == "SHA-160") 193 return new EVPHashFunction(EVP_sha1(), "SHA-160"); 194 } 195 196 static if (!BOTAN_HAS_OPENSSL_NO_SHA256) { 197 if (request.algoName == "SHA-224") 198 return new EVPHashFunction(EVP_sha224(), "SHA-224"); 199 if (request.algoName == "SHA-256") 200 return new EVPHashFunction(EVP_sha256(), "SHA-256"); 201 } 202 203 static if (!BOTAN_HAS_OPENSSL_NO_SHA512) { 204 if (request.algoName == "SHA-384") 205 return new EVPHashFunction(EVP_sha384(), "SHA-384"); 206 if (request.algoName == "SHA-512") 207 return new EVPHashFunction(EVP_sha512(), "SHA-512"); 208 } 209 210 static if (!BOTAN_HAS_OPENSSL_NO_MD4) { 211 if (request.algoName == "MD4") 212 return new EVPHashFunction(EVP_md4(), "MD4"); 213 } 214 215 static if (!BOTAN_HAS_OPENSSL_NO_MD5) { 216 if (request.algoName == "MD5") 217 return new EVPHashFunction(EVP_md5(), "MD5"); 218 } 219 220 static if (!BOTAN_HAS_OPENSSL_NO_RIPEMD) { 221 if (request.algoName == "RIPEMD-160") 222 return new EVPHashFunction(EVP_ripemd160(), "RIPEMD-160"); 223 } 224 225 return null; 226 } 227 MessageAuthenticationCode findMac(in SCANToken algo_spec, AlgorithmFactory af) const 228 { 229 return null; 230 } 231 232 PBKDF findPbkdf(in SCANToken algo_spec, AlgorithmFactory af) const 233 { 234 return null; 235 } 236 237 238 KeyedFilter getCipher(in string algo_spec, CipherDir dir, AlgorithmFactory af) const 239 { 240 return null; 241 } 242 } 243 244 package: 245 246 /* 247 * OpenSSL Modular Exponentiator 248 */ 249 final class OpenSSLModularExponentiator : ModularExponentiator 250 { 251 public: 252 void setBase(const(BigInt)* b) { m_base = OSSL_BN(*b); } 253 254 void setExponent(const(BigInt)* e) { m_exp = OSSL_BN(*e); } 255 256 BigInt execute() const 257 { 258 OSSL_BN r = OSSL_BN(true); 259 BN_mod_exp(r.ptr(), m_base.ptr(), m_exp.ptr(), m_mod.ptr(), m_ctx.getCtx()); 260 return r.toBigint(); 261 } 262 263 ModularExponentiator copy() const 264 { 265 BigInt n = m_mod.toBigint(); 266 OpenSSLModularExponentiator ret = new OpenSSLModularExponentiator(n); 267 ret.m_exp = m_exp; 268 ret.m_base = m_base; 269 270 return ret; 271 } 272 273 this(ref const(BigInt) n) { 274 m_ctx = new OSSL_BN_CTX; 275 m_mod = OSSL_BN(n); 276 } 277 private: 278 this() {} 279 OSSL_BN m_base, m_exp, m_mod; 280 Unique!OSSL_BN_CTX m_ctx; 281 } 282 283 /** 284 * Lightweight OpenSSL BN wrapper. For internal use only. 285 */ 286 struct OSSL_BN 287 { 288 public: 289 /* 290 * OpenSSL to BigInt Conversions 291 */ 292 BigInt toBigint() const 293 { 294 SecureVector!ubyte output = SecureVector!ubyte(bytes()); 295 BN_bn2bin(m_bn, output.ptr); 296 return BigInt.decode(output); 297 } 298 299 /* 300 * Export the BIGNUM as a bytestring 301 */ 302 void encode(ubyte[] output) const 303 { 304 size_t length = output.length; 305 BN_bn2bin(m_bn, output.ptr + (length - bytes())); 306 } 307 308 /* 309 * Return the number of significant bytes 310 */ 311 size_t bytes() const 312 { 313 return BN_num_bytes(m_bn); 314 } 315 316 317 SecureVector!ubyte toBytes() const 318 { 319 return BigInt.encodeLocked(toBigint()); 320 } 321 322 ref typeof(this) opAssign(in OSSL_BN other) 323 { 324 if (m_bn) 325 BN_copy(m_bn, other.m_bn); 326 else m_bn = BN_dup(other.m_bn); 327 return this; 328 } 329 330 /* 331 * OSSL_BN Constructor 332 */ 333 this(const ref BigInt input) 334 { 335 m_bn = BN_new(); 336 SecureVector!ubyte encoding = BigInt.encodeLocked(input); 337 if (input != BigInt(0)) 338 BN_bin2bn(encoding.ptr, cast(int)encoding.length, m_bn); 339 auto ret = toBigint(); 340 } 341 342 /* 343 * OSSL_BN Constructor 344 */ 345 this(const(ubyte)* input, size_t length) 346 { 347 m_bn = BN_new(); 348 BN_bin2bn(input, cast(int)length, m_bn); 349 } 350 351 this(OSSL_BN other) 352 { 353 auto bn = m_bn; 354 m_bn = other.m_bn; 355 other.m_bn = bn; 356 } 357 358 this(bool create) { 359 m_bn = BN_new(); 360 } 361 362 /* 363 * OSSL_BN Destructor 364 */ 365 ~this() const 366 { 367 if (m_bn) 368 BN_clear_free((cast()this).m_bn); 369 } 370 371 BIGNUM* ptr() const { return (cast()this).m_bn; } 372 private: 373 BIGNUM* m_bn; 374 } 375 376 /** 377 * Lightweight OpenSSL BN_CTX wrapper. For internal use only. 378 */ 379 final class OSSL_BN_CTX 380 { 381 public: 382 this(BN_CTX* ctx = null) 383 { 384 m_ctx = BN_CTX_new(); 385 } 386 387 this(in OSSL_BN_CTX bn) 388 { 389 m_ctx = BN_CTX_new(); 390 } 391 392 ~this() 393 { 394 if (m_ctx) 395 BN_CTX_free(m_ctx); 396 } 397 398 BN_CTX* getCtx() const { return (cast()this).m_ctx; } 399 400 private: 401 BN_CTX* m_ctx; 402 } 403 404 405 package: 406 407 /** 408 * RC4 as implemented by OpenSSL 409 */ 410 final class RC4OpenSSL : StreamCipher 411 { 412 public: 413 import botan.utils.mem_ops : clearMem; 414 void clear() { clearMem(&m_state, 1); } 415 416 /* 417 * Return the name of this type 418 */ 419 @property string name() const 420 { 421 if (m_SKIP == 0) return "RC4"; 422 if (m_SKIP == 256) return "MARK-4"; 423 else return "RC4_skip(" ~ to!string(m_SKIP) ~ ")"; 424 } 425 426 StreamCipher clone() const { return new RC4OpenSSL(m_SKIP); } 427 428 KeyLengthSpecification keySpec() const 429 { 430 return KeyLengthSpecification(1, 32); 431 } 432 433 this(size_t s = 0) { m_SKIP = s; clear(); } 434 435 ~this() { clear(); } 436 437 override bool validIvLength(size_t iv_len) const 438 { return (iv_len == 0); } 439 440 override void setIv(const(ubyte)*, size_t iv_len) 441 { 442 if (iv_len) 443 throw new InvalidArgument("The stream cipher " ~ name ~ " does not support resyncronization"); 444 } 445 446 protected: 447 /* 448 * RC4 Encryption 449 */ 450 void cipher(const(ubyte)* input, ubyte* output, size_t length) 451 { 452 RC4(&m_state, cast(int)length, input, output); 453 } 454 455 /* 456 * RC4 Key Schedule 457 */ 458 override void keySchedule(const(ubyte)* key, size_t length) 459 { 460 RC4_set_key(&m_state, cast(int)length, key); 461 ubyte dummy = 0; 462 foreach (size_t i; 0 .. m_SKIP) 463 RC4(&m_state, 1, &dummy, &dummy); 464 } 465 466 const size_t m_SKIP; 467 RC4_KEY m_state; 468 } 469 470 /* 471 * EVP Block Cipher 472 */ 473 final class EVPBlockCipher : BlockCipher, SymmetricAlgorithm 474 { 475 public: 476 /* 477 * Clear memory of sensitive data 478 */ 479 void clear() 480 { 481 const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(m_encrypt); 482 483 EVP_CIPHER_CTX_cleanup(m_encrypt); 484 EVP_CIPHER_CTX_cleanup(m_decrypt); 485 m_encrypt = EVP_CIPHER_CTX_new(); 486 m_decrypt = EVP_CIPHER_CTX_new(); 487 EVP_EncryptInit_ex(m_encrypt, algo, null, null, null); 488 EVP_DecryptInit_ex(m_decrypt, algo, null, null, null); 489 EVP_CIPHER_CTX_set_padding(m_encrypt, 0); 490 EVP_CIPHER_CTX_set_padding(m_decrypt, 0); 491 } 492 493 @property string name() const { return m_cipher_name; } 494 /* 495 * Return a clone of this object 496 */ 497 BlockCipher clone() const 498 { 499 return new EVPBlockCipher(EVP_CIPHER_CTX_cipher(m_encrypt), 500 m_cipher_name, 501 m_cipher_key_spec.minimumKeylength(), 502 m_cipher_key_spec.maximumKeylength(), 503 m_cipher_key_spec.keylengthMultiple()); 504 } 505 506 @property size_t blockSize() const { return m_block_sz; } 507 /* 508 * EVP Block Cipher Constructor 509 */ 510 this(const EVP_CIPHER* algo, 511 in string algo_name) 512 { 513 m_block_sz = EVP_CIPHER_block_size(algo); 514 m_cipher_key_spec = EVP_CIPHER_key_length(algo); 515 m_cipher_name = algo_name; 516 if (EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE) 517 throw new InvalidArgument("EVP_BlockCipher: Non-ECB EVP was passed in"); 518 519 m_encrypt = EVP_CIPHER_CTX_new(); 520 m_decrypt = EVP_CIPHER_CTX_new(); 521 522 EVP_EncryptInit_ex(m_encrypt, algo, null, null, null); 523 EVP_DecryptInit_ex(m_decrypt, algo, null, null, null); 524 525 EVP_CIPHER_CTX_set_padding(m_encrypt, 0); 526 EVP_CIPHER_CTX_set_padding(m_decrypt, 0); 527 } 528 529 530 /* 531 * EVP Block Cipher Constructor 532 */ 533 this(const EVP_CIPHER* algo, 534 in string algo_name, 535 size_t key_min, size_t key_max, 536 size_t key_mod) 537 { 538 m_block_sz = EVP_CIPHER_block_size(algo); 539 m_cipher_key_spec = KeyLengthSpecification(key_min, key_max, key_mod); 540 m_cipher_name = algo_name; 541 if (EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE) 542 throw new InvalidArgument("EVP_BlockCipher: Non-ECB EVP was passed in"); 543 544 m_encrypt = EVP_CIPHER_CTX_new(); 545 m_decrypt = EVP_CIPHER_CTX_new(); 546 547 EVP_EncryptInit_ex(m_encrypt, algo, null, null, null); 548 EVP_DecryptInit_ex(m_decrypt, algo, null, null, null); 549 550 EVP_CIPHER_CTX_set_padding(m_encrypt, 0); 551 EVP_CIPHER_CTX_set_padding(m_decrypt, 0); 552 } 553 554 555 KeyLengthSpecification keySpec() const { return m_cipher_key_spec; } 556 557 /* 558 * EVP Block Cipher Destructor 559 */ 560 ~this() 561 { 562 EVP_CIPHER_CTX_free(m_encrypt); 563 EVP_CIPHER_CTX_free(m_decrypt); 564 } 565 566 override @property size_t parallelism() const { return 1; } 567 protected: 568 /* 569 * Encrypt a block 570 */ 571 void encryptN(const(ubyte)* input, ubyte* output, 572 size_t blocks) 573 { 574 int out_len = 0; 575 EVP_EncryptUpdate(m_encrypt, output, &out_len, input, cast(int)(blocks * m_block_sz)); 576 } 577 578 /* 579 * Decrypt a block 580 */ 581 void decryptN(const(ubyte)* input, ubyte* output, 582 size_t blocks) 583 { 584 int out_len = 0; 585 EVP_DecryptUpdate(m_decrypt, output, &out_len, input, cast(int)(blocks * m_block_sz)); 586 } 587 588 /* 589 * Set the key 590 */ 591 override void keySchedule(const(ubyte)* key, size_t length) 592 { 593 SecureVector!ubyte full_key = SecureVector!ubyte(key[0 .. length]); 594 595 if (m_cipher_name == "TripleDES" && length == 16) 596 { 597 full_key ~= key[0 .. 8]; 598 } 599 else 600 if (EVP_CIPHER_CTX_set_key_length(m_encrypt, cast(int)length) == 0 || 601 EVP_CIPHER_CTX_set_key_length(m_decrypt, cast(int)length) == 0) 602 throw new InvalidArgument("EVP_BlockCipher: Bad key length for " ~ m_cipher_name); 603 604 if (m_cipher_name == "RC2") 605 { 606 EVP_CIPHER_CTX_ctrl(m_encrypt, EVP_CTRL_SET_RC2_KEY_BITS, cast(int)length*8, null); 607 EVP_CIPHER_CTX_ctrl(m_decrypt, EVP_CTRL_SET_RC2_KEY_BITS, cast(int)length*8, null); 608 } 609 610 EVP_EncryptInit_ex(m_encrypt, null, null, full_key.ptr, null); 611 EVP_DecryptInit_ex(m_decrypt, null, null, full_key.ptr, null); 612 } 613 614 size_t m_block_sz; 615 KeyLengthSpecification m_cipher_key_spec; 616 string m_cipher_name; 617 EVP_CIPHER_CTX* m_encrypt, m_decrypt; 618 } 619 620 621 enum string HANDLE_EVP_CIPHER(string NAME, alias EVP) = 622 `if (request.algoName == "` ~ NAME ~ `" && request.argCount() == 0) 623 return new EVPBlockCipher(` ~ __traits(identifier, EVP) ~ `(), "` ~ NAME ~ `");`; 624 625 enum string HANDLE_EVP_CIPHER_KEYLEN(string NAME, alias EVP, int MIN, int MAX, int MOD) = 626 `if (request.algoName == "` ~ NAME ~ `" && request.argCount() == 0) 627 return new EVPBlockCipher(` ~ __traits(identifier, EVP) ~ `(), "` ~ 628 NAME ~ `", ` ~ MIN.stringof ~ `, ` ~ MAX.stringof ~ `, ` ~ MOD.stringof ~ `);`; 629 630 /* 631 * EVP Hash Function 632 */ 633 final class EVPHashFunction : HashFunction 634 { 635 public: 636 /* 637 * Clear memory of sensitive data 638 */ 639 void clear() 640 { 641 const EVP_MD* algo = EVP_MD_CTX_md(m_md); 642 EVP_DigestInit_ex(m_md, algo, null); 643 } 644 645 @property string name() const { return m_algo_name; } 646 /* 647 * Return a clone of this object 648 */ 649 HashFunction clone() const 650 { 651 const EVP_MD* algo = EVP_MD_CTX_md(m_md); 652 return new EVPHashFunction(algo, name); 653 } 654 655 @property size_t outputLength() const 656 { 657 return EVP_MD_size(EVP_MD_CTX_md(m_md)); 658 } 659 660 @property size_t hashBlockSize() const 661 { 662 return EVP_MD_block_size(EVP_MD_CTX_md(m_md)); 663 } 664 /* 665 * Create an EVP hash function 666 */ 667 this(const EVP_MD* algo, 668 in string name) 669 { 670 m_algo_name = name; 671 m_md = EVP_MD_CTX_new(); 672 EVP_DigestInit_ex(m_md, algo, null); 673 } 674 /* 675 * Destroy an EVP hash function 676 */ 677 ~this() 678 { 679 EVP_MD_CTX_free(m_md); 680 } 681 682 protected: 683 684 /* 685 * Update an EVP Hash Calculation 686 */ 687 override void addData(const(ubyte)* input, size_t length) 688 { 689 EVP_DigestUpdate(m_md, input, length); 690 } 691 /* 692 * Finalize an EVP Hash Calculation 693 */ 694 override void finalResult(ubyte* output) 695 { 696 EVP_DigestFinal_ex(m_md, output, null); 697 const EVP_MD* algo = EVP_MD_CTX_md(m_md); 698 EVP_DigestInit_ex(m_md, algo, null); 699 } 700 701 string m_algo_name; 702 EVP_MD_CTX* m_md; 703 } 704 705 706 707 package: 708 709 static if (BOTAN_HAS_DIFFIE_HELLMAN) { 710 final class OSSLDHKAOperation : KeyAgreement 711 { 712 public: 713 this(in PrivateKey pkey) { 714 this(cast(DLSchemePrivateKey) pkey); 715 } 716 717 this(in DHPrivateKey pkey) { 718 this(cast(DLSchemePrivateKey) pkey); 719 } 720 721 this(in DLSchemePrivateKey dh) 722 { 723 assert(dh.algoName == DHPublicKey.algoName); 724 m_ctx = new OSSL_BN_CTX; 725 m_x = dh.getX(); 726 m_p = dh.groupP(); 727 } 728 729 SecureVector!ubyte agree(const(ubyte)* w, size_t w_len) 730 { 731 OSSL_BN i = OSSL_BN(w, w_len); 732 OSSL_BN r = OSSL_BN(true); 733 734 BN_mod_exp(r.ptr(), i.ptr(), m_x.ptr(), m_p.ptr(), m_ctx.getCtx()); 735 return r.toBytes(); 736 } 737 738 private: 739 const OSSL_BN m_x, m_p; 740 Unique!OSSL_BN_CTX m_ctx; 741 } 742 } 743 744 static if (BOTAN_HAS_DSA) { 745 746 final class OSSLDSASignatureOperation : Signature 747 { 748 public: 749 this(in PrivateKey pkey) { 750 this(cast(DLSchemePrivateKey) pkey); 751 } 752 753 this(in DSAPrivateKey pkey) { 754 this(cast(DLSchemePrivateKey) pkey); 755 } 756 757 this(in DLSchemePrivateKey dsa) 758 { 759 assert(dsa.algoName == DSAPublicKey.algoName); 760 m_ctx = new OSSL_BN_CTX(); 761 m_x = dsa.getX(); 762 m_p = dsa.groupP(); 763 m_q = dsa.groupQ(); 764 m_g = dsa.groupG(); 765 m_q_bits = dsa.groupQ().bits(); 766 } 767 768 size_t messageParts() const { return 2; } 769 size_t messagePartSize() const { return (m_q_bits + 7) / 8; } 770 size_t maxInputBits() const { return m_q_bits; } 771 772 SecureVector!ubyte sign(const(ubyte)* msg, size_t msg_len, RandomNumberGenerator rng) 773 { 774 const size_t q_bytes = (m_q_bits + 7) / 8; 775 776 rng.addEntropy(msg, msg_len); 777 778 BigInt k_bn = BigInt(0); 779 do 780 k_bn.randomize(rng, m_q_bits); 781 while (k_bn >= m_q.toBigint()); 782 783 OSSL_BN i = OSSL_BN(msg, msg_len); 784 OSSL_BN k = OSSL_BN(k_bn); 785 786 OSSL_BN r = OSSL_BN(true); 787 BN_mod_exp(r.ptr(), m_g.ptr(), k.ptr(), m_p.ptr(), m_ctx.getCtx()); 788 BN_nnmod(r.ptr(), r.ptr(), m_q.ptr(), m_ctx.getCtx()); 789 790 BN_mod_inverse(k.ptr(), k.ptr(), m_q.ptr(), m_ctx.getCtx()); 791 792 OSSL_BN s = OSSL_BN(true); 793 BN_mul(s.ptr(), m_x.ptr(), r.ptr(), m_ctx.getCtx()); 794 BN_add(s.ptr(), s.ptr(), i.ptr()); 795 BN_mod_mul(s.ptr(), s.ptr(), k.ptr(), m_q.ptr(), m_ctx.getCtx()); 796 797 if (BN_is_zero(r.ptr()) || BN_is_zero(s.ptr())) 798 throw new InternalError("OpenSSL_DSA_Op::sign: r or s was zero"); 799 800 SecureVector!ubyte output = SecureVector!ubyte(2*q_bytes); 801 r.encode(output.ptr[0 .. q_bytes]); 802 s.encode(output.ptr[q_bytes .. output.length]); 803 return output; 804 } 805 806 private: 807 const OSSL_BN m_x, m_p, m_q, m_g; 808 Unique!OSSL_BN_CTX m_ctx; 809 size_t m_q_bits; 810 } 811 812 813 final class OSSLDSAVerificationOperation : Verification 814 { 815 public: 816 this(in PublicKey pkey) { 817 this(cast(DLSchemePublicKey) pkey); 818 } 819 820 this(in DSAPublicKey pkey) { 821 this(cast(DLSchemePublicKey) pkey); 822 } 823 824 this(in DLSchemePublicKey dsa) 825 { 826 assert(dsa.algoName == DSAPublicKey.algoName); 827 m_ctx = new OSSL_BN_CTX(); 828 m_y = dsa.getY(); 829 m_p = dsa.groupP(); 830 m_q = dsa.groupQ(); 831 m_g = dsa.groupG(); 832 m_q_bits = dsa.groupQ().bits(); 833 } 834 835 size_t messageParts() const { return 2; } 836 size_t messagePartSize() const { return (m_q_bits + 7) / 8; } 837 size_t maxInputBits() const { return m_q_bits; } 838 839 bool withRecovery() const { return false; } 840 841 override SecureVector!ubyte verifyMr(const(ubyte)*, size_t) { throw new InvalidState("Message recovery not supported"); } 842 843 bool verify(const(ubyte)* msg, size_t msg_len, 844 const(ubyte)* sig, size_t sig_len) 845 { 846 const size_t q_bytes = m_q.bytes(); 847 848 if (sig_len != 2*q_bytes || msg_len > q_bytes) 849 return false; 850 851 OSSL_BN r = OSSL_BN(sig, q_bytes); 852 OSSL_BN s = OSSL_BN(sig + q_bytes, q_bytes); 853 OSSL_BN i = OSSL_BN(msg, msg_len); 854 855 if (BN_is_zero(r.ptr()) || BN_cmp(r.ptr(), m_q.ptr()) >= 0) 856 return false; 857 if (BN_is_zero(s.ptr()) || BN_cmp(s.ptr(), m_q.ptr()) >= 0) 858 return false; 859 860 if (BN_mod_inverse(s.ptr(), s.ptr(), m_q.ptr(), m_ctx.getCtx()) is null) 861 return false; 862 863 OSSL_BN si = OSSL_BN(true); 864 BN_mod_mul(si.ptr(), s.ptr(), i.ptr(), m_q.ptr(), m_ctx.getCtx()); 865 BN_mod_exp(si.ptr(), m_g.ptr(), si.ptr(), m_p.ptr(), m_ctx.getCtx()); 866 867 OSSL_BN sr = OSSL_BN(true); 868 BN_mod_mul(sr.ptr(), s.ptr(), r.ptr(), m_q.ptr(), m_ctx.getCtx()); 869 BN_mod_exp(sr.ptr(), m_y.ptr(), sr.ptr(), m_p.ptr(), m_ctx.getCtx()); 870 871 BN_mod_mul(si.ptr(), si.ptr(), sr.ptr(), m_p.ptr(), m_ctx.getCtx()); 872 BN_nnmod(si.ptr(), si.ptr(), m_q.ptr(), m_ctx.getCtx()); 873 874 if (BN_cmp(si.ptr(), r.ptr()) == 0) 875 return true; 876 return false; 877 } 878 879 private: 880 const OSSL_BN m_y, m_p, m_q, m_g; 881 Unique!OSSL_BN_CTX m_ctx; 882 size_t m_q_bits; 883 } 884 885 886 static if (BOTAN_HAS_RSA) { 887 888 final class OSSLRSAPrivateOperation : Signature, Decryption 889 { 890 public: 891 this(in PrivateKey pkey) { 892 this(cast(IFSchemePrivateKey) pkey); 893 } 894 895 this(in RSAPrivateKey pkey) { 896 this(cast(IFSchemePrivateKey) pkey); 897 } 898 899 this(in IFSchemePrivateKey rsa) 900 { 901 assert(rsa.algoName == RSAPublicKey.algoName); 902 m_ctx = new OSSL_BN_CTX(); 903 m_mod = OSSL_BN(rsa.getN()); 904 m_q = OSSL_BN(rsa.getQ()); 905 m_c = OSSL_BN(rsa.getC()); 906 m_d1 = OSSL_BN(rsa.getD1()); 907 m_d2 = OSSL_BN(rsa.getD2()); 908 m_p = OSSL_BN(rsa.getP()); 909 m_n_bits = rsa.getN().bits(); 910 } 911 912 size_t maxInputBits() const { return (m_n_bits - 1); } 913 914 SecureVector!ubyte sign(const(ubyte)* msg, size_t msg_len, RandomNumberGenerator) 915 { 916 BigInt m = BigInt(msg, msg_len); 917 BigInt x = privateOp(m); 918 return BigInt.encode1363(x, (m_n_bits + 7) / 8); 919 } 920 921 SecureVector!ubyte decrypt(const(ubyte)* msg, size_t msg_len) 922 { 923 BigInt m = BigInt(msg, msg_len); 924 auto dec = privateOp(m); 925 return BigInt.encodeLocked(dec); 926 } 927 final override size_t messagePartSize() const { 928 return 0; 929 } 930 931 final override size_t messageParts() const { 932 return 1; 933 } 934 935 private: 936 BigInt privateOp(const ref BigInt m) const 937 { 938 OSSL_BN j1 = OSSL_BN(true); 939 OSSL_BN j2 = OSSL_BN(true); 940 OSSL_BN h = OSSL_BN(m); 941 942 BN_mod_exp(j1.ptr(), h.ptr(), m_d1.ptr(), m_p.ptr(), m_ctx.getCtx()); 943 BN_mod_exp(j2.ptr(), h.ptr(), m_d2.ptr(), m_q.ptr(), m_ctx.getCtx()); 944 BN_sub(h.ptr(), j1.ptr(), j2.ptr()); 945 BN_mod_mul(h.ptr(), h.ptr(), m_c.ptr(), m_p.ptr(), m_ctx.getCtx()); 946 BN_mul(h.ptr(), h.ptr(), m_q.ptr(), m_ctx.getCtx()); 947 BN_add(h.ptr(), h.ptr(), j2.ptr()); 948 return h.toBigint(); 949 } 950 951 const OSSL_BN m_mod, m_p, m_q, m_d1, m_d2, m_c; 952 Unique!OSSL_BN_CTX m_ctx; 953 size_t m_n_bits; 954 } 955 956 957 final class OSSLRSAPublicOperation : Verification, Encryption 958 { 959 public: 960 this(in PublicKey pkey) { 961 this(cast(IFSchemePublicKey) pkey); 962 } 963 964 this(in RSAPublicKey pkey) { 965 this(cast(IFSchemePublicKey) pkey); 966 } 967 968 this(in IFSchemePublicKey rsa) 969 { 970 assert(rsa.algoName == RSAPublicKey.algoName); 971 m_ctx = new OSSL_BN_CTX(); 972 m_n = &rsa.getN(); 973 m_e = rsa.getE(); 974 m_mod = rsa.getN(); 975 } 976 977 size_t maxInputBits() const { return (m_n.bits() - 1); } 978 bool withRecovery() const { return true; } 979 980 SecureVector!ubyte encrypt(const(ubyte)* msg, size_t msg_len, RandomNumberGenerator) 981 { 982 BigInt m = BigInt(msg, msg_len); 983 return BigInt.encode1363(publicOp(m), m_n.bytes()); 984 } 985 986 override bool verify(const(ubyte)*, size_t, const(ubyte)*, size_t) 987 { 988 throw new InvalidState("Message recovery required"); 989 } 990 991 override SecureVector!ubyte verifyMr(const(ubyte)* msg, size_t msg_len) 992 { 993 BigInt m = BigInt(msg, msg_len); 994 return BigInt.encodeLocked(publicOp(m)); 995 } 996 final override size_t messagePartSize() const { 997 return 0; 998 } 999 1000 final override size_t messageParts() const { 1001 return 1; 1002 } 1003 1004 private: 1005 BigInt publicOp(const ref BigInt m) const 1006 { 1007 if (m >= *m_n) 1008 throw new InvalidArgument("RSA public op - input is too large"); 1009 1010 OSSL_BN m_bn = OSSL_BN(m); 1011 OSSL_BN r = OSSL_BN(true); 1012 BN_mod_exp(r.ptr(), m_bn.ptr(), m_e.ptr(), m_mod.ptr(), m_ctx.getCtx()); 1013 return r.toBigint(); 1014 } 1015 1016 const BigInt* m_n; 1017 const OSSL_BN m_e, m_mod; 1018 Unique!OSSL_BN_CTX m_ctx; 1019 } 1020 1021 } 1022 1023 }