1 // Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <openssl/dsa.h>
16 
17 #include <stdio.h>
18 #include <string.h>
19 
20 #include <vector>
21 
22 #include <gtest/gtest.h>
23 
24 #include <openssl/bn.h>
25 #include <openssl/crypto.h>
26 #include <openssl/err.h>
27 #include <openssl/pem.h>
28 #include <openssl/span.h>
29 
30 #include "../test/test_util.h"
31 
32 
33 // The following values are taken from the updated Appendix 5 to FIPS PUB 186
34 // and also appear in Appendix 5 to FIPS PUB 186-1.
35 
36 static const uint8_t seed[20] = {
37     0xd5, 0x01, 0x4e, 0x4b, 0x60, 0xef, 0x2b, 0xa8, 0xb6, 0x21, 0x1b,
38     0x40, 0x62, 0xba, 0x32, 0x24, 0xe0, 0x42, 0x7d, 0xd3,
39 };
40 
41 static const uint8_t fips_p[] = {
42     0x8d, 0xf2, 0xa4, 0x94, 0x49, 0x22, 0x76, 0xaa, 0x3d, 0x25, 0x75,
43     0x9b, 0xb0, 0x68, 0x69, 0xcb, 0xea, 0xc0, 0xd8, 0x3a, 0xfb, 0x8d,
44     0x0c, 0xf7, 0xcb, 0xb8, 0x32, 0x4f, 0x0d, 0x78, 0x82, 0xe5, 0xd0,
45     0x76, 0x2f, 0xc5, 0xb7, 0x21, 0x0e, 0xaf, 0xc2, 0xe9, 0xad, 0xac,
46     0x32, 0xab, 0x7a, 0xac, 0x49, 0x69, 0x3d, 0xfb, 0xf8, 0x37, 0x24,
47     0xc2, 0xec, 0x07, 0x36, 0xee, 0x31, 0xc8, 0x02, 0x91,
48 };
49 
50 static const uint8_t fips_q[] = {
51     0xc7, 0x73, 0x21, 0x8c, 0x73, 0x7e, 0xc8, 0xee, 0x99, 0x3b, 0x4f,
52     0x2d, 0xed, 0x30, 0xf4, 0x8e, 0xda, 0xce, 0x91, 0x5f,
53 };
54 
55 static const uint8_t fips_g[] = {
56     0x62, 0x6d, 0x02, 0x78, 0x39, 0xea, 0x0a, 0x13, 0x41, 0x31, 0x63,
57     0xa5, 0x5b, 0x4c, 0xb5, 0x00, 0x29, 0x9d, 0x55, 0x22, 0x95, 0x6c,
58     0xef, 0xcb, 0x3b, 0xff, 0x10, 0xf3, 0x99, 0xce, 0x2c, 0x2e, 0x71,
59     0xcb, 0x9d, 0xe5, 0xfa, 0x24, 0xba, 0xbf, 0x58, 0xe5, 0xb7, 0x95,
60     0x21, 0x92, 0x5c, 0x9c, 0xc4, 0x2e, 0x9f, 0x6f, 0x46, 0x4b, 0x08,
61     0x8c, 0xc5, 0x72, 0xaf, 0x53, 0xe6, 0xd7, 0x88, 0x02,
62 };
63 
64 static const uint8_t fips_x[] = {
65     0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f, 0xde, 0x1c, 0x0f,
66     0xfc, 0x7b, 0x2e, 0x3b, 0x49, 0x8b, 0x26, 0x06, 0x14,
67 };
68 
69 static const uint8_t fips_y[] = {
70     0x19, 0x13, 0x18, 0x71, 0xd7, 0x5b, 0x16, 0x12, 0xa8, 0x19, 0xf2,
71     0x9d, 0x78, 0xd1, 0xb0, 0xd7, 0x34, 0x6f, 0x7a, 0xa7, 0x7b, 0xb6,
72     0x2a, 0x85, 0x9b, 0xfd, 0x6c, 0x56, 0x75, 0xda, 0x9d, 0x21, 0x2d,
73     0x3a, 0x36, 0xef, 0x16, 0x72, 0xef, 0x66, 0x0b, 0x8c, 0x7c, 0x25,
74     0x5c, 0xc0, 0xec, 0x74, 0x85, 0x8f, 0xba, 0x33, 0xf4, 0x4c, 0x06,
75     0x69, 0x96, 0x30, 0xa7, 0x6b, 0x03, 0x0e, 0xe3, 0x33,
76 };
77 
78 static const uint8_t fips_digest[] = {
79     0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, 0x25,
80     0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d,
81 };
82 
83 // fips_sig is a DER-encoded version of the r and s values in FIPS PUB 186-1.
84 static const uint8_t fips_sig[] = {
85     0x30, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10,
86     0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92,
87     0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56,
88     0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6,
89     0xdc, 0xd8, 0xc8,
90 };
91 
92 // fips_sig_negative is fips_sig with r encoded as a negative number.
93 static const uint8_t fips_sig_negative[] = {
94     0x30, 0x2c, 0x02, 0x14, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10, 0x43,
95     0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92, 0xb3,
96     0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56, 0xdf,
97     0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6, 0xdc,
98     0xd8, 0xc8,
99 };
100 
101 // fip_sig_extra is fips_sig with trailing data.
102 static const uint8_t fips_sig_extra[] = {
103     0x30, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64, 0x10,
104     0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92,
105     0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56,
106     0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6,
107     0xdc, 0xd8, 0xc8, 0x00,
108 };
109 
110 // fips_sig_lengths is fips_sig with a non-minimally encoded length.
111 static const uint8_t fips_sig_bad_length[] = {
112     0x30, 0x81, 0x2d, 0x02, 0x15, 0x00, 0x8b, 0xac, 0x1a, 0xb6, 0x64,
113     0x10, 0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c,
114     0x92, 0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f,
115     0x56, 0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d,
116     0xb6, 0xdc, 0xd8, 0xc8, 0x00,
117 };
118 
119 // fips_sig_bad_r is fips_sig with a bad r value.
120 static const uint8_t fips_sig_bad_r[] = {
121     0x30, 0x2d, 0x02, 0x15, 0x00, 0x8c, 0xac, 0x1a, 0xb6, 0x64, 0x10,
122     0x43, 0x5c, 0xb7, 0x18, 0x1f, 0x95, 0xb1, 0x6a, 0xb9, 0x7c, 0x92,
123     0xb3, 0x41, 0xc0, 0x02, 0x14, 0x41, 0xe2, 0x34, 0x5f, 0x1f, 0x56,
124     0xdf, 0x24, 0x58, 0xf4, 0x26, 0xd1, 0x55, 0xb4, 0xba, 0x2d, 0xb6,
125     0xdc, 0xd8, 0xc8,
126 };
127 
GetFIPSDSAGroup(void)128 static bssl::UniquePtr<DSA> GetFIPSDSAGroup(void) {
129   bssl::UniquePtr<DSA> dsa(DSA_new());
130   if (!dsa) {
131     return nullptr;
132   }
133   bssl::UniquePtr<BIGNUM> p(BN_bin2bn(fips_p, sizeof(fips_p), nullptr));
134   bssl::UniquePtr<BIGNUM> q(BN_bin2bn(fips_q, sizeof(fips_q), nullptr));
135   bssl::UniquePtr<BIGNUM> g(BN_bin2bn(fips_g, sizeof(fips_g), nullptr));
136   if (!p || !q || !g || !DSA_set0_pqg(dsa.get(), p.get(), q.get(), g.get())) {
137     return nullptr;
138   }
139   // |DSA_set0_pqg| takes ownership.
140   p.release();
141   q.release();
142   g.release();
143   return dsa;
144 }
145 
GetFIPSDSA(void)146 static bssl::UniquePtr<DSA> GetFIPSDSA(void) {
147   bssl::UniquePtr<DSA> dsa = GetFIPSDSAGroup();
148   if (!dsa) {
149     return nullptr;
150   }
151   bssl::UniquePtr<BIGNUM> pub_key(BN_bin2bn(fips_y, sizeof(fips_y), nullptr));
152   bssl::UniquePtr<BIGNUM> priv_key(BN_bin2bn(fips_x, sizeof(fips_x), nullptr));
153   if (!pub_key || !priv_key ||
154       !DSA_set0_key(dsa.get(), pub_key.get(), priv_key.get())) {
155     return nullptr;
156   }
157   // |DSA_set0_key| takes ownership.
158   pub_key.release();
159   priv_key.release();
160   return dsa;
161 }
162 
TEST(DSATest,Generate)163 TEST(DSATest, Generate) {
164   bssl::UniquePtr<DSA> dsa(DSA_new());
165   ASSERT_TRUE(dsa);
166   int counter;
167   unsigned long h;
168   ASSERT_TRUE(DSA_generate_parameters_ex(dsa.get(), 512, seed, 20, &counter, &h,
169                                          nullptr));
170   EXPECT_EQ(counter, 105);
171   EXPECT_EQ(h, 2u);
172 
173   auto expect_bn_bytes = [](const char *msg, const BIGNUM *bn,
174                             bssl::Span<const uint8_t> bytes) {
175     std::vector<uint8_t> buf(BN_num_bytes(bn));
176     BN_bn2bin(bn, buf.data());
177     EXPECT_EQ(Bytes(buf), Bytes(bytes)) << msg;
178   };
179   expect_bn_bytes("q value is wrong", DSA_get0_q(dsa.get()), fips_q);
180   expect_bn_bytes("p value is wrong", DSA_get0_p(dsa.get()), fips_p);
181   expect_bn_bytes("g value is wrong", DSA_get0_g(dsa.get()), fips_g);
182 
183   ASSERT_TRUE(DSA_generate_key(dsa.get()));
184 
185   std::vector<uint8_t> sig(DSA_size(dsa.get()));
186   unsigned sig_len;
187   ASSERT_TRUE(DSA_sign(0, fips_digest, sizeof(fips_digest), sig.data(),
188                        &sig_len, dsa.get()));
189 
190   EXPECT_EQ(1, DSA_verify(0, fips_digest, sizeof(fips_digest), sig.data(),
191                           sig_len, dsa.get()));
192 }
193 
TEST(DSATest,GenerateParamsTooLarge)194 TEST(DSATest, GenerateParamsTooLarge) {
195   bssl::UniquePtr<DSA> dsa(DSA_new());
196   ASSERT_TRUE(dsa);
197   EXPECT_FALSE(DSA_generate_parameters_ex(
198       dsa.get(), 10001, /*seed=*/nullptr, /*seed_len=*/0,
199       /*out_counter=*/nullptr, /*out_h=*/nullptr,
200       /*cb=*/nullptr));
201 }
202 
TEST(DSATest,GenerateKeyTooLarge)203 TEST(DSATest, GenerateKeyTooLarge) {
204   bssl::UniquePtr<DSA> dsa = GetFIPSDSA();
205   ASSERT_TRUE(dsa);
206   bssl::UniquePtr<BIGNUM> large_p(BN_new());
207   ASSERT_TRUE(large_p);
208   ASSERT_TRUE(BN_set_bit(large_p.get(), 10001));
209   ASSERT_TRUE(BN_set_bit(large_p.get(), 0));
210   ASSERT_TRUE(DSA_set0_pqg(dsa.get(), /*p=*/large_p.get(), /*q=*/nullptr,
211                            /*g=*/nullptr));
212   large_p.release();  // |DSA_set0_pqg| takes ownership on success.
213 
214   // Don't generate DSA keys if the group is too large.
215   EXPECT_FALSE(DSA_generate_key(dsa.get()));
216 }
217 
TEST(DSATest,Verify)218 TEST(DSATest, Verify) {
219   bssl::UniquePtr<DSA> dsa = GetFIPSDSA();
220   ASSERT_TRUE(dsa);
221 
222   EXPECT_EQ(1, DSA_verify(0, fips_digest, sizeof(fips_digest), fips_sig,
223                           sizeof(fips_sig), dsa.get()));
224   EXPECT_EQ(-1,
225             DSA_verify(0, fips_digest, sizeof(fips_digest), fips_sig_negative,
226                        sizeof(fips_sig_negative), dsa.get()));
227   EXPECT_EQ(-1, DSA_verify(0, fips_digest, sizeof(fips_digest), fips_sig_extra,
228                            sizeof(fips_sig_extra), dsa.get()));
229   EXPECT_EQ(-1,
230             DSA_verify(0, fips_digest, sizeof(fips_digest), fips_sig_bad_length,
231                        sizeof(fips_sig_bad_length), dsa.get()));
232   EXPECT_EQ(0, DSA_verify(0, fips_digest, sizeof(fips_digest), fips_sig_bad_r,
233                           sizeof(fips_sig_bad_r), dsa.get()));
234 }
235 
TEST(DSATest,InvalidGroup)236 TEST(DSATest, InvalidGroup) {
237   bssl::UniquePtr<DSA> dsa = GetFIPSDSA();
238   ASSERT_TRUE(dsa);
239   bssl::UniquePtr<BIGNUM> zero(BN_new());
240   ASSERT_TRUE(zero);
241   ASSERT_TRUE(DSA_set0_pqg(dsa.get(), /*p=*/nullptr, /*q=*/nullptr,
242                            /*g=*/zero.release()));
243 
244   std::vector<uint8_t> sig(DSA_size(dsa.get()));
245   unsigned sig_len;
246   static const uint8_t kDigest[32] = {0};
247   EXPECT_FALSE(
248       DSA_sign(0, kDigest, sizeof(kDigest), sig.data(), &sig_len, dsa.get()));
249   EXPECT_TRUE(
250       ErrorEquals(ERR_get_error(), ERR_LIB_DSA, DSA_R_INVALID_PARAMETERS));
251 }
252 
253 // Signing and verifying should cleanly fail when the DSA object is empty.
TEST(DSATest,MissingParameters)254 TEST(DSATest, MissingParameters) {
255   bssl::UniquePtr<DSA> dsa(DSA_new());
256   ASSERT_TRUE(dsa);
257   EXPECT_EQ(-1, DSA_verify(0, fips_digest, sizeof(fips_digest), fips_sig,
258                            sizeof(fips_sig), dsa.get()));
259 
260   std::vector<uint8_t> sig(DSA_size(dsa.get()));
261   unsigned sig_len;
262   EXPECT_FALSE(DSA_sign(0, fips_digest, sizeof(fips_digest), sig.data(),
263                         &sig_len, dsa.get()));
264 }
265 
266 // Verifying should cleanly fail when the public key is missing.
TEST(DSATest,MissingPublic)267 TEST(DSATest, MissingPublic) {
268   bssl::UniquePtr<DSA> dsa = GetFIPSDSAGroup();
269   ASSERT_TRUE(dsa);
270   EXPECT_EQ(-1, DSA_verify(0, fips_digest, sizeof(fips_digest), fips_sig,
271                            sizeof(fips_sig), dsa.get()));
272 }
273 
274 // Signing should cleanly fail when the private key is missing.
TEST(DSATest,MissingPrivate)275 TEST(DSATest, MissingPrivate) {
276   bssl::UniquePtr<DSA> dsa = GetFIPSDSAGroup();
277   ASSERT_TRUE(dsa);
278 
279   std::vector<uint8_t> sig(DSA_size(dsa.get()));
280   unsigned sig_len;
281   EXPECT_FALSE(DSA_sign(0, fips_digest, sizeof(fips_digest), sig.data(),
282                         &sig_len, dsa.get()));
283 }
284 
285 // A zero private key is invalid and can cause signing to loop forever.
TEST(DSATest,ZeroPrivateKey)286 TEST(DSATest, ZeroPrivateKey) {
287   bssl::UniquePtr<DSA> dsa = GetFIPSDSA();
288   ASSERT_TRUE(dsa);
289   bssl::UniquePtr<BIGNUM> zero(BN_new());
290   ASSERT_TRUE(zero);
291   ASSERT_TRUE(DSA_set0_key(dsa.get(), /*pub_key=*/nullptr,
292                            /*priv_key=*/zero.release()));
293 
294   static const uint8_t kZeroDigest[32] = {0};
295   std::vector<uint8_t> sig(DSA_size(dsa.get()));
296   unsigned sig_len;
297   EXPECT_FALSE(DSA_sign(0, kZeroDigest, sizeof(kZeroDigest), sig.data(),
298                         &sig_len, dsa.get()));
299 }
300 
301 // If the "field" is actually a ring and the "generator" of the multiplicative
302 // subgroup is actually nilpotent with low degree, DSA signing never completes.
303 // Test that we give up in the infinite loop.
TEST(DSATest,NilpotentGenerator)304 TEST(DSATest, NilpotentGenerator) {
305   static const char kPEM[] = R"(
306 -----BEGIN DSA PRIVATE KEY-----
307 MGECAQACFQHH+MnFXh4NNlZiV/zUVb5a5ib3kwIVAOP8ZOKvDwabKzEr/moq3y1z
308 E3vJAhUAl/2Ylx9fWbzHdh1URsc/c6IM/TECAQECFCsjU4AZRcuks45g1NMOUeCB
309 Epvg
310 -----END DSA PRIVATE KEY-----
311 )";
312   bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(kPEM, sizeof(kPEM)));
313   ASSERT_TRUE(bio);
314   bssl::UniquePtr<DSA> dsa(
315       PEM_read_bio_DSAPrivateKey(bio.get(), nullptr, nullptr, nullptr));
316   ASSERT_TRUE(dsa);
317 
318   std::vector<uint8_t> sig(DSA_size(dsa.get()));
319   unsigned sig_len;
320   EXPECT_FALSE(DSA_sign(0, fips_digest, sizeof(fips_digest), sig.data(),
321                         &sig_len, dsa.get()));
322 }
323 
TEST(DSATest,Overwrite)324 TEST(DSATest, Overwrite) {
325   // Load an arbitrary DSA private key and use it.
326   static const char kPEM[] = R"(
327 -----BEGIN DSA PRIVATE KEY-----
328 MIIDTgIBAAKCAQEAyH68EuravtF+7PTFBtWJkwjmp0YJmh8e2Cdpu8ci3dZf87rk
329 GwXzfqYkAEkW5H4Hp0cxdICKFiqfxjSaiEauOrNV+nXWZS634hZ9H47I8HnAVS0p
330 5MmSmPJ7NNUowymMpyB6M6hfqHl/1pZd7avbTmnzb2SZ0kw0WLWJo6vMekepYWv9
331 3o1Xove4ci00hnkr7Qo9Bh/+z84jgeT2/MTdsCVtbuMv/mbcYLhCKVWPBozDZr/D
332 qwhGTlomsTRvP3WIbem3b5eYhQaPuMsKiAzntcinoxQXWrIoZB+xJyF/sI013uBI
333 i9ePSxY3704U4QGxVM0aR/6fzORz5kh8ZjhhywIdAI9YBUR6eoGevUaLq++qXiYW
334 TgXBXlyqE32ESbkCggEBAL/c5GerO5g25D0QsfgVIJtlZHQOwYauuWoUudaQiyf6
335 VhWLBNNTAGldkFGdtxsA42uqqZSXCki25LvN6PscGGvFy8oPWaa9TGt+l9Z5ZZiV
336 ShNpg71V9YuImsPB3BrQ4L6nZLfhBt6InzJ6KqjDNdg7u6lgnFKue7l6khzqNxbM
337 RgxHWMq7PkhMcl+RzpqbiGcxSHqraxldutqCWsnZzhKh4d4GdunuRY8GiFo0Axkb
338 Kn0Il3zm81ewv08F/ocu+IZQEzxTyR8YRQ99MLVbnwhVxndEdLjjetCX82l+/uEY
339 5fdUy0thR8odcDsvUc/tT57I+yhnno80HbpUUNw2+/sCggEAdh1wp/9CifYIp6T8
340 P/rIus6KberZ2Pv/n0bl+Gv8AoToA0zhZXIfY2l0TtanKmdLqPIvjqkN0v6zGSs+
341 +ahR1QzMQnK718mcsQmB4X6iP5LKgJ/t0g8LrDOxc/cNycmHq76MmF9RN5NEBz4+
342 PAnRIftm/b0UQflP6uy3gRQP2X7P8ZebCytOPKTZC4oLyCtvPevSkCiiauq/RGjL
343 k6xqRgLxMtmuyhT+dcVbtllV1p1xd9Bppnk17/kR5VCefo/e/7DHu163izRDW8tx
344 SrEmiVyVkRijY3bVZii7LPfMz5eEAWEDJRuFwyNv3i6j7CKeZw2d/hzu370Ua28F
345 s2lmkAIcLIFUDFrbC2nViaB5ATM9ARKk6F2QwnCfGCyZ6A==
346 -----END DSA PRIVATE KEY-----
347 )";
348   bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(kPEM, sizeof(kPEM)));
349   ASSERT_TRUE(bio);
350   bssl::UniquePtr<DSA> dsa(
351       PEM_read_bio_DSAPrivateKey(bio.get(), nullptr, nullptr, nullptr));
352   ASSERT_TRUE(dsa);
353 
354   std::vector<uint8_t> sig(DSA_size(dsa.get()));
355   unsigned sig_len;
356   ASSERT_TRUE(DSA_sign(0, fips_digest, sizeof(fips_digest), sig.data(),
357                        &sig_len, dsa.get()));
358   sig.resize(sig_len);
359   EXPECT_EQ(1, DSA_verify(0, fips_digest, sizeof(fips_digest), sig.data(),
360                           sig.size(), dsa.get()));
361 
362   // Overwrite it with the sample key.
363   bssl::UniquePtr<BIGNUM> p(BN_bin2bn(fips_p, sizeof(fips_p), nullptr));
364   ASSERT_TRUE(p);
365   bssl::UniquePtr<BIGNUM> q(BN_bin2bn(fips_q, sizeof(fips_q), nullptr));
366   ASSERT_TRUE(q);
367   bssl::UniquePtr<BIGNUM> g(BN_bin2bn(fips_g, sizeof(fips_g), nullptr));
368   ASSERT_TRUE(g);
369   ASSERT_TRUE(DSA_set0_pqg(dsa.get(), p.get(), q.get(), g.get()));
370   // |DSA_set0_pqg| takes ownership on success.
371   p.release();
372   q.release();
373   g.release();
374   bssl::UniquePtr<BIGNUM> pub_key(BN_bin2bn(fips_y, sizeof(fips_y), nullptr));
375   ASSERT_TRUE(pub_key);
376   bssl::UniquePtr<BIGNUM> priv_key(BN_bin2bn(fips_x, sizeof(fips_x), nullptr));
377   ASSERT_TRUE(priv_key);
378   ASSERT_TRUE(DSA_set0_key(dsa.get(), pub_key.get(), priv_key.get()));
379   // |DSA_set0_key| takes ownership on success.
380   pub_key.release();
381   priv_key.release();
382 
383   // The key should now work correctly for the new parameters.
384   EXPECT_EQ(1, DSA_verify(0, fips_digest, sizeof(fips_digest), fips_sig,
385                           sizeof(fips_sig), dsa.get()));
386 
387   // Test signing by verifying it round-trips through the real key.
388   sig.resize(DSA_size(dsa.get()));
389   ASSERT_TRUE(DSA_sign(0, fips_digest, sizeof(fips_digest), sig.data(),
390                        &sig_len, dsa.get()));
391   sig.resize(sig_len);
392   dsa = GetFIPSDSA();
393   ASSERT_TRUE(dsa);
394   EXPECT_EQ(1, DSA_verify(0, fips_digest, sizeof(fips_digest), sig.data(),
395                           sig.size(), dsa.get()));
396 }
397