Blob CngKey::Export(CngKeyBlobFormat format) const { EVP_PKEY* key = ToKey(_self); Blob r; int size; byte *buf; switch (format) { case CngKeyBlobFormat::OSslEccPrivateBlob: SslCheck((size = ::i2d_PrivateKey(key, 0)) >= 0); r.Size = size; SslCheck(::i2d_PrivateKey(key, &(buf = r.data())) == size); break; case CngKeyBlobFormat::OSslEccPrivateBignum: { const BIGNUM *bn = ::EC_KEY_get0_private_key(key->pkey.ec); SslCheck(bn); r.Size = BN_num_bytes(bn); if (::BN_bn2bin(bn, r.data()) != r.Size) Throw(E_FAIL); } break; case CngKeyBlobFormat::OSslEccPublicBlob: // SslCheck(size = ::i2o_ECPublicKey(key, 0)); SslCheck((size = ::i2d_PublicKey(key, 0)) >= 0); r.Size = size; // SslCheck(::i2o_ECPublicKey(key, &(buf = r.data())) == size); SslCheck(::i2d_PublicKey(key, &(buf = r.data())) == size); break; case CngKeyBlobFormat::OSslEccPublicCompressedBlob: { CngKey tmp = _self; key = ToKey(tmp); ::EC_KEY_set_conv_form(key->pkey.ec, POINT_CONVERSION_COMPRESSED); r = tmp.Export(CngKeyBlobFormat::OSslEccPublicBlob); } break; case CngKeyBlobFormat::OSslEccPublicUncompressedBlob: { CngKey tmp = _self; key = ToKey(tmp); ::EC_KEY_set_conv_form(key->pkey.ec, POINT_CONVERSION_UNCOMPRESSED); r = tmp.Export(CngKeyBlobFormat::OSslEccPublicBlob); } break; case CngKeyBlobFormat::OSslEccPrivateCompressedBlob: { CngKey tmp = _self; key = ToKey(tmp); ::EC_KEY_set_conv_form(key->pkey.ec, POINT_CONVERSION_COMPRESSED); r = tmp.Export(CngKeyBlobFormat::OSslEccPrivateBlob); } break; default: Throw(E_INVALIDARG); } return r; }
Blob ECDsa::SignHash(const ConstBuf& hash) { EC_KEY *ecKey = ToKey(Key)->pkey.ec; int size = ::ECDSA_size(ecKey); SslCheck(size); Blob r(0, size); unsigned int nSize = 0; SslCheck(::ECDSA_sign(0, hash.P, hash.Size, r.data(), &nSize, ecKey) > 0); r.Size = nSize; return r; }
void OpensslBn::ToBinary(byte *p, size_t n) const { int a = BN_num_bytes(m_bn); if (a > n) Throw(E_INVALIDARG); memset(p, 0, n-a); SslCheck(::BN_bn2bin(m_bn, p+(n-a))); }
OpensslBn::OpensslBn(const BigInteger& bn) { int n = (bn.Length+8)/8; byte *p = (byte*)alloca(n); bn.ToBytes(p, n); std::reverse(p, p+n); SslCheck(m_bn = ::BN_bin2bn(p, n, 0)); }
void OpensslBn::ToBinary(uint8_t *p, size_t n) const { int a = BN_num_bytes(m_bn); if (a > n) Throw(errc::invalid_argument); memset(p, 0, n-a); SslCheck(::BN_bn2bin(m_bn, p+(n-a))); }
BigInteger sqrt_mod(const BigInteger& x, const BigInteger& mod) { OpensslBn v(x), m(mod), r; BnCtx ctx; SslCheck(::BN_mod_sqrt(r.Ref(), v, m, ctx)); return r.ToBigInteger(); }
ECDsa::ECDsa(int keySize) : base(0) { EC_KEY *key; switch (keySize) { case 256: key = EC_KEY_new_by_curve_name(NID_secp256k1); break; case 384: key = EC_KEY_new_by_curve_name(NID_secp384r1); break; case 521: key = EC_KEY_new_by_curve_name(NID_secp521r1); break; default: Throw(E_INVALIDARG); } EVP_PKEY *impl = ::EVP_PKEY_new(); SslCheck(::EVP_PKEY_set_type(impl, EVP_PKEY_EC)); impl->pkey.ec = key; SslCheck(Key.m_pimpl = impl); SslCheck(::EC_KEY_generate_key(key)); }
EcKey(int nid) { SslCheck(m_key = ::EC_KEY_new_by_curve_name(nid)); }
bool ECDsa::VerifyHash(const ConstBuf& hash, const ConstBuf& signature) { int rc = ::ECDSA_verify(0, hash.P, hash.Size, signature.P, signature.Size, ToKey(Key)->pkey.ec); SslCheck(rc >= 0); return rc; }
OpensslBn OpensslBn::FromBinary(RCSpan cbuf) { BIGNUM *a = ::BN_bin2bn(cbuf.data(), cbuf.size(), 0); SslCheck(a); return OpensslBn(a); }
EcPoint& operator=(const EcPoint& ecPoint) { ::EC_POINT_free(m_point); SslCheck(m_point = ::EC_POINT_dup(ecPoint.m_point, m_group = ecPoint.m_group)); }
EcPoint(const EC_GROUP *group) { SslCheck(m_point = ::EC_POINT_new(m_group = group)); }
OpensslBn OpensslBn::FromBinary(const ConstBuf& cbuf) { BIGNUM *a = ::BN_bin2bn(cbuf.P, cbuf.Size, 0); SslCheck(a); return OpensslBn(a); }
void Random::NextBytes(const Buf& mb) { SslCheck(::RAND_bytes(mb.P, mb.Size) > 0); }
EcKey(const EcKey& ecKey) { SslCheck(::EC_KEY_up_ref(m_key = ecKey.m_key)); }
EcKey& operator=(const EcKey& ecKey) { ::EC_KEY_free(m_key); SslCheck(::EC_KEY_up_ref(m_key = ecKey.m_key)); return *this; }
OpenSslMalloc::OpenSslMalloc() { SslCheck(::CRYPTO_set_mem_functions(&OpenSslMallocFun, &OpenSslRealloc, &OpenSslFree)); }
EcPoint(const EcPoint& ecPoint) { SslCheck(m_point = ::EC_POINT_dup(ecPoint.m_point, m_group = ecPoint.m_group)); }
CngKey CngKey::Import(const ConstBuf& mb, CngKeyBlobFormat format) { const byte *p = mb.P; EVP_PKEY *impl = 0; EC_KEY *ec_key; switch (format) { case CngKeyBlobFormat::OSslEccPrivateBlob: //!!!SslCheck(::d2i_ECPrivateKey((EC_KEY**)&impl, &p, mb.m_len)); impl = ::EVP_PKEY_new(); SslCheck(::EVP_PKEY_set_type(impl, EVP_PKEY_EC)); SslCheck(ec_key = ::EC_KEY_new_by_curve_name(NID_secp256k1)); impl->pkey.ec = ec_key; SslCheck(::d2i_ECPrivateKey(&impl->pkey.ec, &p, mb.Size)); break; case CngKeyBlobFormat::OSslEccPrivateBignum: { impl = ::EVP_PKEY_new(); SslCheck(::EVP_PKEY_set_type(impl, EVP_PKEY_EC)); SslCheck(ec_key = ::EC_KEY_new_by_curve_name(NID_secp256k1)); impl->pkey.ec = ec_key; OpensslBn bn = OpensslBn::FromBinary(mb); EcPoint ecPoint(::EC_KEY_get0_group(ec_key)); ecPoint.Mul(bn); SslCheck(::EC_KEY_set_private_key(ec_key, bn)); SslCheck(::EC_KEY_set_public_key(ec_key, ecPoint)); } break; case CngKeyBlobFormat::OSslEccPublicBlob: //!!!SslCheck(impl = ::d2i_PublicKey(EVP_PKEY_EC, &impl, &p, mb.m_len)); impl = ::EVP_PKEY_new(); SslCheck(::EVP_PKEY_set_type(impl, EVP_PKEY_EC)); SslCheck(ec_key = ::EC_KEY_new_by_curve_name(NID_secp256k1)); impl->pkey.ec = ec_key; SslCheck(::o2i_ECPublicKey(&impl->pkey.ec, &p, mb.Size)); break; case CngKeyBlobFormat::OSslEccPublicCompressedBlob: impl = ::EVP_PKEY_new(); SslCheck(::EVP_PKEY_set_type(impl, EVP_PKEY_EC)); SslCheck(ec_key = ::EC_KEY_new_by_curve_name(NID_secp256k1)); impl->pkey.ec = ec_key; SslCheck(::o2i_ECPublicKey(&impl->pkey.ec, &p, mb.Size)); ::EC_KEY_set_conv_form(impl->pkey.ec, POINT_CONVERSION_COMPRESSED); break; default: Throw(E_INVALIDARG); } return CngKey(impl); }
void Mul(const OpensslBn& bn) { BnCtx bnCtx; SslCheck(::EC_POINT_mul(m_group, m_point, bn, 0, 0, bnCtx)); }
void Random::NextBytes(const span<uint8_t>& mb) { SslCheck(::RAND_bytes(mb.data(), mb.size()) > 0); }