Repository: randombit/botan
Pull request #2055 (2019-08-01 13:27:24)

Updates for GOST 2012 support
It turns out GOST certs/CSRs use IEEE1363 style signature formatting rather than using DER structure.

GH #1860 #1897


Patch:
diff --git a/src/build-data/oids.txt b/src/build-data/oids.txt
index f47e2e5de..b17d8b611 100644
--- a/src/build-data/oids.txt
+++ b/src/build-data/oids.txt
@@ -33,6 +33,8 @@
 1.0.14888.3.0.5 = ECKCDSA
 
 1.2.643.2.2.19 = GOST-34.10
+1.2.643.7.1.1.1.1 = GOST-34.10-2012-256
+1.2.643.7.1.1.1.2 = GOST-34.10-2012-512
 
 # OpenPGP (RFC4880bis)
 1.3.6.1.4.1.11591.15.1 = OpenPGP.Ed25519
@@ -121,9 +123,6 @@
 2.16.840.1.101.3.4.2.11 = SHAKE-128
 2.16.840.1.101.3.4.2.12 = SHAKE-256
 
-1.2.643.7.1.1.2.2 = Streebog-256
-1.2.643.7.1.1.2.3 = Streebog-512
-
 [mac]
 # MACs
 1.2.840.113549.2.7 = HMAC(SHA-160)
@@ -199,6 +198,10 @@
 1.2.410.200004.1.100.4.5 = ECKCDSA/EMSA1(SHA-256)
 
 1.2.643.2.2.3 = GOST-34.10/EMSA1(GOST-R-34.11-94)
+1.2.643.7.1.1.2.2 = Streebog-256
+1.2.643.7.1.1.2.3 = Streebog-512
+
+1.2.643.7.1.1.3.2 = GOST-34.10/EMSA1(Streebog-256)
 
 1.3.6.1.4.1.25258.1.6.1 = GOST-34.10/EMSA1(SHA-256)
 
@@ -214,6 +217,7 @@
 2.5.4.6 = X520.Country = 3
 2.5.4.7 = X520.Locality = 128
 2.5.4.8 = X520.State = 128
+2.5.4.9 = X520.StreetAddress = 128
 2.5.4.10 = X520.Organization = 64
 2.5.4.11 = X520.OrganizationalUnit = 64
 2.5.4.12 = X520.Title = 64
@@ -242,6 +246,7 @@
 [pkix]
 2.5.29.14 = X509v3.SubjectKeyIdentifier
 2.5.29.15 = X509v3.KeyUsage
+2.5.29.16 = X509v3.PrivateKeyUsagePeriod
 2.5.29.17 = X509v3.SubjectAlternativeName
 2.5.29.18 = X509v3.IssuerAlternativeName
 2.5.29.19 = X509v3.BasicConstraints
@@ -260,6 +265,12 @@
 
 2.5.29.32.0 = X509v3.AnyPolicy
 
+1.2.643.100.111 = GOST.SubjectSigningTool
+1.2.643.100.112 = GOST.IssuerSigningTool
+
+1.2.643.100.1 = GOST.OGRN
+1.2.643.3.131.1.1 = GOST.INN
+
 1.3.6.1.5.5.7.3.1 = PKIX.ServerAuth
 1.3.6.1.5.5.7.3.2 = PKIX.ClientAuth
 1.3.6.1.5.5.7.3.3 = PKIX.CodeSigning
@@ -312,6 +323,11 @@
 1.3.36.3.3.2.8.1.1.11 = brainpool384r1
 1.3.36.3.3.2.8.1.1.13 = brainpool512r1
 
+1.2.250.1.223.101.256.1 = frp256v1
+
+1.2.643.7.1.2.1.1.1 = gost_256A
+1.2.643.7.1.2.1.1.2 = gost_256B
+1.2.643.7.1.2.1.2.1 = gost_512A
+1.2.643.7.1.2.1.2.2 = gost_512B
 1.2.643.2.2.35.1 = gost_256A
 1.2.643.2.2.36.0 = gost_256A
-1.2.250.1.223.101.256.1 = frp256v1
diff --git a/src/lib/asn1/oid_maps.cpp b/src/lib/asn1/oid_maps.cpp
index ed1e3df38..0072f989b 100644
--- a/src/lib/asn1/oid_maps.cpp
+++ b/src/lib/asn1/oid_maps.cpp
@@ -1,7 +1,7 @@
 /*
 * OID maps
 *
-* This file was automatically generated by ./src/scripts/oids.py on 2019-06-23
+* This file was automatically generated by ./src/scripts/oids.py on 2019-08-01
 *
 * All manual edits to this file will be lost. Edit the script
 * then regenerate this source file.
@@ -39,12 +39,23 @@ std::unordered_map<std::string, std::string> OIDS::load_oid2str_map()
       { "1.2.410.200004.1.100.4.4", "ECKCDSA/EMSA1(SHA-224)" },
       { "1.2.410.200004.1.100.4.5", "ECKCDSA/EMSA1(SHA-256)" },
       { "1.2.410.200004.1.4", "SEED/CBC" },
+      { "1.2.643.100.1", "GOST.OGRN" },
+      { "1.2.643.100.111", "GOST.SubjectSigningTool" },
+      { "1.2.643.100.112", "GOST.IssuerSigningTool" },
       { "1.2.643.2.2.19", "GOST-34.10" },
       { "1.2.643.2.2.3", "GOST-34.10/EMSA1(GOST-R-34.11-94)" },
       { "1.2.643.2.2.35.1", "gost_256A" },
       { "1.2.643.2.2.36.0", "gost_256A" },
+      { "1.2.643.3.131.1.1", "GOST.INN" },
+      { "1.2.643.7.1.1.1.1", "GOST-34.10-2012-256" },
+      { "1.2.643.7.1.1.1.2", "GOST-34.10-2012-512" },
       { "1.2.643.7.1.1.2.2", "Streebog-256" },
       { "1.2.643.7.1.1.2.3", "Streebog-512" },
+      { "1.2.643.7.1.1.3.2", "GOST-34.10/EMSA1(Streebog-256)" },
+      { "1.2.643.7.1.2.1.1.1", "gost_256A" },
+      { "1.2.643.7.1.2.1.1.2", "gost_256B" },
+      { "1.2.643.7.1.2.1.2.1", "gost_512A" },
+      { "1.2.643.7.1.2.1.2.2", "gost_512B" },
       { "1.2.840.10040.4.1", "DSA" },
       { "1.2.840.10040.4.3", "DSA/EMSA1(SHA-160)" },
       { "1.2.840.10045.2.1", "ECDSA" },
@@ -213,6 +224,7 @@ std::unordered_map<std::string, std::string> OIDS::load_oid2str_map()
       { "2.16.840.1.113730.1.13", "Certificate Comment" },
       { "2.5.29.14", "X509v3.SubjectKeyIdentifier" },
       { "2.5.29.15", "X509v3.KeyUsage" },
+      { "2.5.29.16", "X509v3.PrivateKeyUsagePeriod" },
       { "2.5.29.17", "X509v3.SubjectAlternativeName" },
       { "2.5.29.18", "X509v3.IssuerAlternativeName" },
       { "2.5.29.19", "X509v3.BasicConstraints" },
@@ -242,6 +254,7 @@ std::unordered_map<std::string, std::string> OIDS::load_oid2str_map()
       { "2.5.4.65", "X520.Pseudonym" },
       { "2.5.4.7", "X520.Locality" },
       { "2.5.4.8", "X520.State" },
+      { "2.5.4.9", "X520.StreetAddress" },
       { "2.5.8.1.1", "RSA" }
       };
    }
@@ -318,8 +331,15 @@ std::unordered_map<std::string, OID> OIDS::load_str2oid_map()
       { "Ed25519", OID({1,3,101,112}) },
       { "ElGamal", OID({1,3,6,1,4,1,3029,1,2,1}) },
       { "GOST-34.10", OID({1,2,643,2,2,19}) },
+      { "GOST-34.10-2012-256", OID({1,2,643,7,1,1,1,1}) },
+      { "GOST-34.10-2012-512", OID({1,2,643,7,1,1,1,2}) },
       { "GOST-34.10/EMSA1(GOST-R-34.11-94)", OID({1,2,643,2,2,3}) },
       { "GOST-34.10/EMSA1(SHA-256)", OID({1,3,6,1,4,1,25258,1,6,1}) },
+      { "GOST-34.10/EMSA1(Streebog-256)", OID({1,2,643,7,1,1,3,2}) },
+      { "GOST.INN", OID({1,2,643,3,131,1,1}) },
+      { "GOST.IssuerSigningTool", OID({1,2,643,100,112}) },
+      { "GOST.OGRN", OID({1,2,643,100,1}) },
+      { "GOST.SubjectSigningTool", OID({1,2,643,100,111}) },
       { "HMAC(SHA-160)", OID({1,2,840,113549,2,7}) },
       { "HMAC(SHA-224)", OID({1,2,840,113549,2,8}) },
       { "HMAC(SHA-256)", OID({1,2,840,113549,2,9}) },
@@ -429,6 +449,7 @@ std::unordered_map<std::string, OID> OIDS::load_str2oid_map()
       { "X509v3.KeyUsage", OID({2,5,29,15}) },
       { "X509v3.NameConstraints", OID({2,5,29,30}) },
       { "X509v3.PolicyConstraints", OID({2,5,29,36}) },
+      { "X509v3.PrivateKeyUsagePeriod", OID({2,5,29,16}) },
       { "X509v3.ReasonCode", OID({2,5,29,21}) },
       { "X509v3.SubjectAlternativeName", OID({2,5,29,17}) },
       { "X509v3.SubjectKeyIdentifier", OID({2,5,29,14}) },
@@ -444,6 +465,7 @@ std::unordered_map<std::string, OID> OIDS::load_str2oid_map()
       { "X520.Pseudonym", OID({2,5,4,65}) },
       { "X520.SerialNumber", OID({2,5,4,5}) },
       { "X520.State", OID({2,5,4,8}) },
+      { "X520.StreetAddress", OID({2,5,4,9}) },
       { "X520.Surname", OID({2,5,4,4}) },
       { "X520.Title", OID({2,5,4,12}) },
       { "XMSS", OID({1,3,6,1,4,1,25258,1,8}) },
@@ -456,7 +478,10 @@ std::unordered_map<std::string, OID> OIDS::load_str2oid_map()
       { "brainpool384r1", OID({1,3,36,3,3,2,8,1,1,11}) },
       { "brainpool512r1", OID({1,3,36,3,3,2,8,1,1,13}) },
       { "frp256v1", OID({1,2,250,1,223,101,256,1}) },
-      { "gost_256A", OID({1,2,643,2,2,35,1}) },
+      { "gost_256A", OID({1,2,643,7,1,2,1,1,1}) },
+      { "gost_256B", OID({1,2,643,7,1,2,1,1,2}) },
+      { "gost_512A", OID({1,2,643,7,1,2,1,2,1}) },
+      { "gost_512B", OID({1,2,643,7,1,2,1,2,2}) },
       { "secp160k1", OID({1,3,132,0,9}) },
       { "secp160r1", OID({1,3,132,0,8}) },
       { "secp160r2", OID({1,3,132,0,30}) },
diff --git a/src/lib/pubkey/ec_group/ec_named.cpp b/src/lib/pubkey/ec_group/ec_named.cpp
index ba91b5eaa..7fe1517e4 100644
--- a/src/lib/pubkey/ec_group/ec_named.cpp
+++ b/src/lib/pubkey/ec_group/ec_named.cpp
@@ -114,14 +114,25 @@ std::shared_ptr<EC_Group_Data> EC_Group::EC_group_info(const OID& oid)
                                 "0xF1FD178C0B3AD58F10126DE8CE42435B53DC67E140D2BF941FFDD459C6D655E1",
                                 oid);
    // gost_256A
-   if(oid == OID{1,2,643,2,2,35,1})
+   if(oid == OID{1,2,643,2,2,35,1} || oid == OID{1,2,643,2,2,36,0} || oid == OID{1,2,643,7,1,2,1,1,1})
       return load_EC_group_info("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97",
                                 "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94",
                                 "0xA6",
                                 "0x1",
                                 "0x8D91E471E0989CDA27DF505A453F2B7635294F2DDF23E3B122ACC99C9E9F1E14",
                                 "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C611070995AD10045841B09B761B893",
+                                OID{1,2,643,7,1,2,1,1,1});
+
+   // gost_512A
+   if(oid == OID{1,2,643,7,1,2,1,2,1})
+      return load_EC_group_info("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7",
+                                "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4",
+                                "0xE8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760",
+                                "3",
+                                "0x7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4",
+                                "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275",
                                 oid);
+
    // secp160k1
    if(oid == OID{1,3,132,0,9})
       return load_EC_group_info("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
@@ -281,6 +292,7 @@ const std::set<std::string>& EC_Group::known_named_groups()
       "x962_p239v2",
       "x962_p239v3",
       "gost_256A",
+      "gost_512A",
       "frp256v1",
       "sm2p256v1"
       };
diff --git a/src/lib/pubkey/ecc_key/info.txt b/src/lib/pubkey/ecc_key/info.txt
index f46c9bb54..32d05f2f9 100644
--- a/src/lib/pubkey/ecc_key/info.txt
+++ b/src/lib/pubkey/ecc_key/info.txt
@@ -1,5 +1,6 @@
 <defines>
 ECC_PUBLIC_KEY_CRYPTO -> 20131128
+ECC_KEY -> 20190801
 </defines>
 
 <requires>
diff --git a/src/lib/pubkey/gost_3410/gost_3410.h b/src/lib/pubkey/gost_3410/gost_3410.h
index 52b6ad758..8c42f5091 100644
--- a/src/lib/pubkey/gost_3410/gost_3410.h
+++ b/src/lib/pubkey/gost_3410/gost_3410.h
@@ -53,6 +53,9 @@ class BOTAN_PUBLIC_API(2,0) GOST_3410_PublicKey : public virtual EC_PublicKey
       size_t message_part_size() const override
          { return domain().get_order().bytes(); }
 
+      Signature_Format default_x509_signature_format() const
+         { return IEEE_1363; }
+
       std::unique_ptr<PK_Ops::Verification>
          create_verification_op(const std::string& params,
                                 const std::string& provider) const override;
diff --git a/src/lib/pubkey/gost_3410/info.txt b/src/lib/pubkey/gost_3410/info.txt
index c51b75ce5..805e31485 100644
--- a/src/lib/pubkey/gost_3410/info.txt
+++ b/src/lib/pubkey/gost_3410/info.txt
@@ -1,5 +1,6 @@
 <defines>
 GOST_34_10_2001 -> 20131128
+GOST_34_10_2012 -> 20190801
 </defines>
 
 <requires>
diff --git a/src/lib/pubkey/pk_algs.cpp b/src/lib/pubkey/pk_algs.cpp
index 16bfbfb1f..126f27cd4 100644
--- a/src/lib/pubkey/pk_algs.cpp
+++ b/src/lib/pubkey/pk_algs.cpp
@@ -146,7 +146,7 @@ load_public_key(const AlgorithmIdentifier& alg_id,
 #endif
 
 #if defined(BOTAN_HAS_GOST_34_10_2001)
-   if(alg_name == "GOST-34.10")
+   if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" || alg_name == "GOST-34.10-2012-512")
       return std::unique_ptr<Public_Key>(new GOST_3410_PublicKey(alg_id, key_bits));
 #endif
 
@@ -222,7 +222,7 @@ load_private_key(const AlgorithmIdentifier& alg_id,
 #endif
 
 #if defined(BOTAN_HAS_GOST_34_10_2001)
-   if(alg_name == "GOST-34.10")
+   if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" || alg_name == "GOST-34.10-2012-512")
       return std::unique_ptr<Private_Key>(new GOST_3410_PrivateKey(alg_id, key_bits));
 #endif
 
diff --git a/src/lib/pubkey/pk_keys.h b/src/lib/pubkey/pk_keys.h
index 0aa9caf54..e7e86d8fa 100644
--- a/src/lib/pubkey/pk_keys.h
+++ b/src/lib/pubkey/pk_keys.h
@@ -18,6 +18,11 @@ namespace Botan {
 
 class RandomNumberGenerator;
 
+/**
+* The two types of signature format supported by Botan.
+*/
+enum Signature_Format { IEEE_1363, DER_SEQUENCE };
+
 /**
 * Public Key Base Class.
 */
@@ -118,6 +123,11 @@ class BOTAN_PUBLIC_API(2,0) Public_Key
       */
       virtual size_t message_part_size() const { return 0; }
 
+      virtual Signature_Format default_x509_signature_format() const
+         {
+         return (this->message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
+         }
+
       /**
       * This is an internal library function exposed on key types.
       * In almost all cases applications should use wrappers in pubkey.h
diff --git a/src/lib/pubkey/pubkey.h b/src/lib/pubkey/pubkey.h
index dc4ef6ee6..2aa8ea916 100644
--- a/src/lib/pubkey/pubkey.h
+++ b/src/lib/pubkey/pubkey.h
@@ -22,11 +22,6 @@ namespace Botan {
 
 class RandomNumberGenerator;
 
-/**
-* The two types of signature format supported by Botan.
-*/
-enum Signature_Format { IEEE_1363, DER_SEQUENCE };
-
 /**
 * Public Key Encryptor
 * This is the primary interface for public key encryption
diff --git a/src/lib/x509/ocsp.cpp b/src/lib/x509/ocsp.cpp
index 7907d08e2..249ce7817 100644
--- a/src/lib/x509/ocsp.cpp
+++ b/src/lib/x509/ocsp.cpp
@@ -170,7 +170,7 @@ Certificate_Status_Code Response::verify_signature(const X509_Certificate& issue
          return Certificate_Status_Code::OCSP_RESPONSE_INVALID;
 
       std::string padding = sig_info[1];
-      Signature_Format format = (pub_key->message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
+      const Signature_Format format = pub_key->default_x509_signature_format();
 
       PK_Verifier verifier(*pub_key, padding, format);
 
diff --git a/src/lib/x509/x509_obj.cpp b/src/lib/x509/x509_obj.cpp
index 74786c224..a48e088ac 100644
--- a/src/lib/x509/x509_obj.cpp
+++ b/src/lib/x509/x509_obj.cpp
@@ -197,8 +197,7 @@ Certificate_Status_Code X509_Object::verify_signature(const Public_Key& pub_key)
    else
       return Certificate_Status_Code::SIGNATURE_ALGO_BAD_PARAMS;
 
-   const Signature_Format format =
-      (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
+   const Signature_Format format = pub_key.default_x509_signature_format();
 
    if(padding == "EMSA4")
       {
@@ -369,7 +368,7 @@ std::unique_ptr<PK_Signer> X509_Object::choose_sig_format(AlgorithmIdentifier& s
                                                           const std::string& hash_fn,
                                                           const std::string& padding_algo)
    {
-   const Signature_Format format = (key.message_parts() > 1) ? DER_SEQUENCE : IEEE_1363;
+   const Signature_Format format = key.default_x509_signature_format();
 
    const std::string emsa = choose_sig_algo(sig_algo, key, hash_fn, padding_algo);
 


Test patch:
diff --git a/src/tests/data/x509/gost/gost_int.pem b/src/tests/data/x509/gost/gost_int.pem
new file mode 100644
index 000000000..16e823470
--- /dev/null
+++ b/src/tests/data/x509/gost/gost_int.pem
@@ -0,0 +1,46 @@
+-----BEGIN CERTIFICATE-----
+MIIIJzCCB9SgAwIBAgIRAdE5xgDlqVW1So99yFUKb2YwCgYIKoUDBwEBAwIwggFV
+MSAwHgYJKoZIhvcNAQkBFhFpbmZvQGNyeXB0b3Byby5ydTEYMBYGBSqFA2QBEg0x
+MDM3NzAwMDg1NDQ0MRowGAYIKoUDA4EDAQESDDAwNzcxNzEwNzk5MTELMAkGA1UE
+BhMCUlUxGDAWBgNVBAgMDzc3INCc0L7RgdC60LLQsDEVMBMGA1UEBwwM0JzQvtGB
+0LrQstCwMS8wLQYDVQQJDCbRg9C7LiDQodGD0YnRkdCy0YHQutC40Lkg0LLQsNC7
+INC0LiAxODElMCMGA1UECgwc0J7QntCeICLQmtCg0JjQn9Ci0J4t0J/QoNCeIjFl
+MGMGA1UEAwxc0KLQtdGB0YLQvtCy0YvQuSDQs9C+0LvQvtCy0L3QvtC5INCj0KYg
+0J7QntCeICLQmtCg0JjQn9Ci0J4t0J/QoNCeIiDQk9Ce0KHQoiAyMDEyICjQo9Cm
+IDIuMCkwHhcNMTkwMTMwMTE1MTQ0WhcNMjkwMTMwMTIwMTQ0WjCCAVsxIDAeBgkq
+hkiG9w0BCQEWEWluZm9AY3J5cHRvcHJvLnJ1MRgwFgYFKoUDZAESDTEwMzc3MDAw
+ODU0NDQxGjAYBggqhQMDgQMBARIMMDA3NzE3MTA3OTkxMQswCQYDVQQGEwJSVTEY
+MBYGA1UECAwPNzcg0JzQvtGB0LrQstCwMRUwEwYDVQQHDAzQnNC+0YHQutCy0LAx
+LzAtBgNVBAkMJtGD0LsuINCh0YPRidGR0LLRgdC60LjQuSDQstCw0Lsg0LQuIDE4
+MSUwIwYDVQQKDBzQntCe0J4gItCa0KDQmNCf0KLQni3Qn9Cg0J4iMWswaQYDVQQD
+DGLQotC10YHRgtC+0LLRi9C5INC/0L7QtNGH0LjQvdC10L3QvdGL0Lkg0KPQpiDQ
+ntCe0J4gItCa0KDQmNCf0KLQni3Qn9Cg0J4iINCT0J7QodCiIDIwMTIgKNCj0KYg
+Mi4wKTBmMB8GCCqFAwcBAQEBMBMGByqFAwICIwEGCCqFAwcBAQICA0MABEACB5tW
+0cRZuiQIXwccPDntbVUxlWm9sFPnZiH8T2ZUGtQA5uqSDZAd8sk2Zv0OpBdFEMty
+g98vg/M36Vw24G0io4IEbDCCBGgwPwYFKoUDZG8ENgw00KHQmtCX0JggItCa0YDQ
+uNC/0YLQvtCf0YDQviBDU1AiICjQstC10YDRgdC40Y8gNC4wKTASBgkrBgEEAYI3
+FQEEBQIDAQABMB0GA1UdDgQWBBT/5GhgksjsgRMZu5Y141hB8YEtmzAOBgNVHQ8B
+Af8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAlBgNVHSAEHjAcMAYGBFUdIAAw
+CAYGKoUDZHEBMAgGBiqFA2RxAjBrBggrBgEFBQcBAQRfMF0wWwYIKwYBBQUHMAKG
+T2h0dHA6Ly90ZXN0Y2EyMDEyLmNyeXB0b3Byby5ydS9haWEvY2IxZGJiODQzNmEx
+ODI4YTU5NDkxOTViY2I0OWMxOTkyZTMxYmE4NC5jcnQwHwYJKwYBBAGCNxUHBBIw
+EAYIKoUDAgIuAAECAQECAQAwggEaBgUqhQNkcASCAQ8wggELDDTQodCa0JfQmCAi
+0JrRgNC40L/RgtC+0J/RgNC+IENTUCIgKNCy0LXRgNGB0LjRjyA0LjApDDHQn9CQ
+0JogItCa0YDQuNC/0YLQvtCf0YDQviDQo9CmIiDQstC10YDRgdC40LggMi4wDE/Q
+odC10YDRgtC40YTQuNC60LDRgiDRgdC+0L7RgtCy0LXRgtGB0YLQstC40Y8g4oSW
+INCh0KQvMTI0LTMzODAg0L7RgiAxMS4wNS4yMDE4DE/QodC10YDRgtC40YTQuNC6
+0LDRgiDRgdC+0L7RgtCy0LXRgtGB0YLQstC40Y8g4oSWINCh0KQvMTI4LTM1OTIg
+0L7RgiAxNy4xMC4yMDE4MGAGA1UdHwRZMFcwVaBToFGGT2h0dHA6Ly90ZXN0Y2Ey
+MDEyLmNyeXB0b3Byby5ydS9jZHAvY2IxZGJiODQzNmExODI4YTU5NDkxOTViY2I0
+OWMxOTkyZTMxYmE4NC5jcmwwggGXBgNVHSMEggGOMIIBioAUyx27hDahgopZSRlb
+y0nBmS4xuoShggFdpIIBWTCCAVUxIDAeBgkqhkiG9w0BCQEWEWluZm9AY3J5cHRv
+cHJvLnJ1MRgwFgYFKoUDZAESDTEwMzc3MDAwODU0NDQxGjAYBggqhQMDgQMBARIM
+MDA3NzE3MTA3OTkxMQswCQYDVQQGEwJSVTEYMBYGA1UECAwPNzcg0JzQvtGB0LrQ
+stCwMRUwEwYDVQQHDAzQnNC+0YHQutCy0LAxLzAtBgNVBAkMJtGD0LsuINCh0YPR
+idGR0LLRgdC60LjQuSDQstCw0Lsg0LQuIDE4MSUwIwYDVQQKDBzQntCe0J4gItCa
+0KDQmNCf0KLQni3Qn9Cg0J4iMWUwYwYDVQQDDFzQotC10YHRgtC+0LLRi9C5INCz
+0L7Qu9C+0LLQvdC+0Lkg0KPQpiDQntCe0J4gItCa0KDQmNCf0KLQni3Qn9Cg0J4i
+INCT0J7QodCiIDIwMTIgKNCj0KYgMi4wKYIRAdSExQDlqfiOTLgOyPFzGK8wCgYI
+KoUDBwEBAwIDQQBSins81hN4Uja8J+Wfx2p+9A8I+DmsgbL594z6+m7Fv7jwlJjH
+khx+dTtOs+9dzw0pbq5QmmsL2RdzR19VfGGh
+-----END CERTIFICATE-----
diff --git a/src/tests/data/x509/gost/gost_root.pem b/src/tests/data/x509/gost/gost_root.pem
new file mode 100644
index 000000000..e45fff2ab
--- /dev/null
+++ b/src/tests/data/x509/gost/gost_root.pem
@@ -0,0 +1,33 @@
+-----BEGIN CERTIFICATE-----
+MIIFxzCCBXSgAwIBAgIRAdSExQDlqfiOTLgOyPFzGK8wCgYIKoUDBwEBAwIwggFV
+MSAwHgYJKoZIhvcNAQkBFhFpbmZvQGNyeXB0b3Byby5ydTEYMBYGBSqFA2QBEg0x
+MDM3NzAwMDg1NDQ0MRowGAYIKoUDA4EDAQESDDAwNzcxNzEwNzk5MTELMAkGA1UE
+BhMCUlUxGDAWBgNVBAgMDzc3INCc0L7RgdC60LLQsDEVMBMGA1UEBwwM0JzQvtGB
+0LrQstCwMS8wLQYDVQQJDCbRg9C7LiDQodGD0YnRkdCy0YHQutC40Lkg0LLQsNC7
+INC0LiAxODElMCMGA1UECgwc0J7QntCeICLQmtCg0JjQn9Ci0J4t0J/QoNCeIjFl
+MGMGA1UEAwxc0KLQtdGB0YLQvtCy0YvQuSDQs9C+0LvQvtCy0L3QvtC5INCj0KYg
+0J7QntCeICLQmtCg0JjQn9Ci0J4t0J/QoNCeIiDQk9Ce0KHQoiAyMDEyICjQo9Cm
+IDIuMCkwHhcNMTkwMTMwMTE0OTA5WhcNMzQwMTMwMTE0OTA5WjCCAVUxIDAeBgkq
+hkiG9w0BCQEWEWluZm9AY3J5cHRvcHJvLnJ1MRgwFgYFKoUDZAESDTEwMzc3MDAw
+ODU0NDQxGjAYBggqhQMDgQMBARIMMDA3NzE3MTA3OTkxMQswCQYDVQQGEwJSVTEY
+MBYGA1UECAwPNzcg0JzQvtGB0LrQstCwMRUwEwYDVQQHDAzQnNC+0YHQutCy0LAx
+LzAtBgNVBAkMJtGD0LsuINCh0YPRidGR0LLRgdC60LjQuSDQstCw0Lsg0LQuIDE4
+MSUwIwYDVQQKDBzQntCe0J4gItCa0KDQmNCf0KLQni3Qn9Cg0J4iMWUwYwYDVQQD
+DFzQotC10YHRgtC+0LLRi9C5INCz0L7Qu9C+0LLQvdC+0Lkg0KPQpiDQntCe0J4g
+ItCa0KDQmNCf0KLQni3Qn9Cg0J4iINCT0J7QodCiIDIwMTIgKNCj0KYgMi4wKTBm
+MB8GCCqFAwcBAQEBMBMGByqFAwICIwEGCCqFAwcBAQICA0MABEAAltiwjies7KjL
+BzOmQzGhJ8gGcwrceeVaj5RM/dwEoHLY4/xVoQAZzA6MsWW3hOfcEwVNw+y7FqNi
+S40X7/x9o4ICEjCCAg4wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTLHbuENqGC
+illJGVvLScGZLjG6hDAPBgNVHRMBAf8EBTADAQH/MCUGA1UdIAQeMBwwBgYEVR0g
+ADAIBgYqhQNkcQEwCAYGKoUDZHECMIIBGgYFKoUDZHAEggEPMIIBCww00KHQmtCX
+0JggItCa0YDQuNC/0YLQvtCf0YDQviBDU1AiICjQstC10YDRgdC40Y8gNC4wKQwx
+0J/QkNCaICLQmtGA0LjQv9GC0L7Qn9GA0L4g0KPQpiIg0LLQtdGA0YHQuNC4IDIu
+MAxP0KHQtdGA0YLQuNGE0LjQutCw0YIg0YHQvtC+0YLQstC10YLRgdGC0LLQuNGP
+IOKEliDQodCkLzEyNC0zMzgwINC+0YIgMTEuMDUuMjAxOAxP0KHQtdGA0YLQuNGE
+0LjQutCw0YIg0YHQvtC+0YLQstC10YLRgdGC0LLQuNGPIOKEliDQodCkLzEyOC0z
+NTkyINC+0YIgMTcuMTAuMjAxODA/BgUqhQNkbwQ2DDTQodCa0JfQmCAi0JrRgNC4
+0L/RgtC+0J/RgNC+IENTUCIgKNCy0LXRgNGB0LjRjyA0LjApMBEGCSsGAQQBgjcU
+AgQEDAJDQTASBgkrBgEEAYI3FQEEBQIDAQABMB8GCSsGAQQBgjcVBwQSMBAGCCqF
+AwICLgAAAgEBAgEAMAoGCCqFAwcBAQMCA0EA5HjDmdzd2XU9A5SUbH1JRWr7OnUW
+Q/3Pde0fc9C2UUnBDvtJPmDgPqvv3ho3trV015ktc8p00v+A9Erolsd5Ig==
+-----END CERTIFICATE-----
diff --git a/src/tests/unit_ecc.cpp b/src/tests/unit_ecc.cpp
index 28b2fadd1..08d08b516 100644
--- a/src/tests/unit_ecc.cpp
+++ b/src/tests/unit_ecc.cpp
@@ -9,16 +9,17 @@
 #include "tests.h"
 
 #if defined(BOTAN_HAS_ECC_GROUP)
-#include <botan/bigint.h>
-#include <botan/numthry.h>
-#include <botan/curve_nistp.h>
-#include <botan/pk_keys.h>
-#include <botan/point_gfp.h>
-#include <botan/ec_group.h>
-#include <botan/reducer.h>
-#include <botan/hex.h>
-#include <botan/data_src.h>
-#include <botan/x509_key.h>
+  #include <botan/bigint.h>
+  #include <botan/numthry.h>
+  #include <botan/curve_nistp.h>
+  #include <botan/pk_keys.h>
+  #include <botan/point_gfp.h>
+  #include <botan/ec_group.h>
+  #include <botan/reducer.h>
+  #include <botan/hex.h>
+  #include <botan/data_src.h>
+  #include <botan/x509_key.h>
+  #include <botan/oids.h>
 #endif
 
 namespace Botan_Tests {
@@ -273,7 +274,9 @@ class EC_Group_Tests : public Test
             {
             Test::Result result("EC_Group " + group_name);
 
-            const Botan::EC_Group group(group_name);
+            const Botan::OID oid = Botan::OIDS::lookup(group_name);
+
+            const Botan::EC_Group group(oid);
 
             result.confirm("EC_Group is known", !group.get_curve_oid().empty());
             result.confirm("EC_Group is considered valid", group.verify_group(Test::rng(), true));
diff --git a/src/tests/unit_x509.cpp b/src/tests/unit_x509.cpp
index 29739eb85..69ffe3823 100644
--- a/src/tests/unit_x509.cpp
+++ b/src/tests/unit_x509.cpp
@@ -558,6 +558,33 @@ Test::Result test_x509_authority_info_access_extension()
    return result;
    }
 
+Test::Result test_verify_gost2012_cert()
+   {
+   Test::Result result("X509 GOST-2012 certificates");
+
+#if defined(BOTAN_HAS_GOST_34_10_2012) && defined(BOTAN_HAS_STREEBOG)
+   try
+      {
+      Botan::X509_Certificate root_cert(Test::data_file("x509/gost/gost_root.pem"));
+      Botan::X509_Certificate root_int(Test::data_file("x509/gost/gost_int.pem"));
+
+      Botan::Certificate_Store_In_Memory trusted;
+      trusted.add_certificate(root_cert);
+
+      const Botan::Path_Validation_Restrictions restrictions(false, 128, false, {"Streebog-256"});
+      const Botan::Path_Validation_Result validation_result = Botan::x509_path_validate(root_int, restrictions, trusted);
+
+      result.confirm("GOST certificate validates", validation_result.successful_validation());
+      }
+   catch(const Botan::Decoding_Error& e)
+      {
+      result.test_failure(e.what());
+      }
+#endif
+
+   return result;
+   }
+
 /*
  * @brief checks the configurability of the EMSA4(RSA-PSS) signature scheme
  *
@@ -1617,6 +1644,7 @@ class X509_Cert_Unit_Tests final : public Test
          results.push_back(test_x509_decode_list());
          results.push_back(test_rsa_oaep());
          results.push_back(test_x509_authority_info_access_extension());
+         results.push_back(test_verify_gost2012_cert());
 #endif
 
          results.push_back(test_x509_dates());