xref: /aosp_15_r20/external/cronet/third_party/boringssl/src/crypto/evp/p_dh_asn1.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 /*
2  * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <openssl/evp.h>
11 
12 #include <openssl/bn.h>
13 #include <openssl/dh.h>
14 #include <openssl/err.h>
15 
16 #include "internal.h"
17 #include "../internal.h"
18 
19 
dh_free(EVP_PKEY * pkey)20 static void dh_free(EVP_PKEY *pkey) {
21   DH_free(pkey->pkey);
22   pkey->pkey = NULL;
23 }
24 
dh_size(const EVP_PKEY * pkey)25 static int dh_size(const EVP_PKEY *pkey) { return DH_size(pkey->pkey); }
26 
dh_bits(const EVP_PKEY * pkey)27 static int dh_bits(const EVP_PKEY *pkey) { return DH_bits(pkey->pkey); }
28 
dh_param_missing(const EVP_PKEY * pkey)29 static int dh_param_missing(const EVP_PKEY *pkey) {
30   const DH *dh = pkey->pkey;
31   return dh == NULL || DH_get0_p(dh) == NULL || DH_get0_g(dh) == NULL;
32 }
33 
dh_param_copy(EVP_PKEY * to,const EVP_PKEY * from)34 static int dh_param_copy(EVP_PKEY *to, const EVP_PKEY *from) {
35   if (dh_param_missing(from)) {
36     OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
37     return 0;
38   }
39 
40   const DH *dh = from->pkey;
41   const BIGNUM *q_old = DH_get0_q(dh);
42   BIGNUM *p = BN_dup(DH_get0_p(dh));
43   BIGNUM *q = q_old == NULL ? NULL : BN_dup(q_old);
44   BIGNUM *g = BN_dup(DH_get0_g(dh));
45   if (p == NULL || (q_old != NULL && q == NULL) || g == NULL ||
46       !DH_set0_pqg(to->pkey, p, q, g)) {
47     BN_free(p);
48     BN_free(q);
49     BN_free(g);
50     return 0;
51   }
52 
53   // |DH_set0_pqg| took ownership of |p|, |q|, and |g|.
54   return 1;
55 }
56 
dh_param_cmp(const EVP_PKEY * a,const EVP_PKEY * b)57 static int dh_param_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
58   if (dh_param_missing(a) || dh_param_missing(b)) {
59     return -2;
60   }
61 
62   // Matching OpenSSL, only compare p and g for PKCS#3-style Diffie-Hellman.
63   // OpenSSL only checks q in X9.42-style Diffie-Hellman ("DHX").
64   const DH *a_dh = a->pkey;
65   const DH *b_dh = b->pkey;
66   return BN_cmp(DH_get0_p(a_dh), DH_get0_p(b_dh)) == 0 &&
67          BN_cmp(DH_get0_g(a_dh), DH_get0_g(b_dh)) == 0;
68 }
69 
dh_pub_cmp(const EVP_PKEY * a,const EVP_PKEY * b)70 static int dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
71   if (dh_param_cmp(a, b) <= 0) {
72     return 0;
73   }
74 
75   const DH *a_dh = a->pkey;
76   const DH *b_dh = b->pkey;
77   return BN_cmp(DH_get0_pub_key(a_dh), DH_get0_pub_key(b_dh)) == 0;
78 }
79 
80 const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
81     .pkey_id = EVP_PKEY_DH,
82     .pkey_method = &dh_pkey_meth,
83     .pub_cmp = dh_pub_cmp,
84     .pkey_size = dh_size,
85     .pkey_bits = dh_bits,
86     .param_missing = dh_param_missing,
87     .param_copy = dh_param_copy,
88     .param_cmp = dh_param_cmp,
89     .pkey_free = dh_free,
90 };
91 
EVP_PKEY_set1_DH(EVP_PKEY * pkey,DH * key)92 int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key) {
93   if (EVP_PKEY_assign_DH(pkey, key)) {
94     DH_up_ref(key);
95     return 1;
96   }
97   return 0;
98 }
99 
EVP_PKEY_assign_DH(EVP_PKEY * pkey,DH * key)100 int EVP_PKEY_assign_DH(EVP_PKEY *pkey, DH *key) {
101   evp_pkey_set_method(pkey, &dh_asn1_meth);
102   pkey->pkey = key;
103   return key != NULL;
104 }
105 
EVP_PKEY_get0_DH(const EVP_PKEY * pkey)106 DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey) {
107   if (pkey->type != EVP_PKEY_DH) {
108     OPENSSL_PUT_ERROR(EVP, EVP_R_EXPECTING_A_DH_KEY);
109     return NULL;
110   }
111   return pkey->pkey;
112 }
113 
EVP_PKEY_get1_DH(const EVP_PKEY * pkey)114 DH *EVP_PKEY_get1_DH(const EVP_PKEY *pkey) {
115   DH *dh = EVP_PKEY_get0_DH(pkey);
116   if (dh != NULL) {
117     DH_up_ref(dh);
118   }
119   return dh;
120 }
121