xref: /optee_os/core/lib/libtomcrypt/src/pk/dh/dh_make_key.c (revision 9f543cd3f8c72fe38d157f808e6b0d2a329cf37e)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2001-2007, Tom St Denis
4  * Copyright (c) 2014, STMicroelectronics International N.V.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "tomcrypt_private.h"
31 #include <stdint.h>
32 
33 /*
34  * Make a DH key [private key pair]
35  * @param prng     An active PRNG state
36  * @param wprng    The index for the PRNG you desire to use
37  * @param keysize  The key size (octets) desired of the private key
38  * @param q        If not null, then the private key is in the range
39  *                 [2, q-2] where q is called the subprime
40  * @param xbits    If not 0, then the private key has 'xbits' bits
41  * @note           The private key must always be less than p-1
42  * @param key      [in/out] Where the newly created DH key will be stored
43  *                  g and p are provided as input in the key
44  *                  type, x and y are output of this function
45  * @return CRYPT_OK if successful, note: on error all allocated memory will be
46  *         freed automatically.
47 */
48 
dh_make_key(prng_state * prng,int wprng,void * q,int xbits,dh_key * key)49 int dh_make_key(prng_state *prng, int wprng, void *q, int xbits, dh_key *key)
50 {
51 	int err = 0;
52 	int key_size = 0;	/* max key size, in bytes */
53 	int key_size_p = 0;	/* key size of p */
54 	int key_size_q = 0;	/* key size of p */
55 	void *arg_mod = 0;
56 	uint8_t *buf = 0;	/* intermediate buffer to have a raw random  */
57 
58 	/*
59 	 * Check the arguments
60 	 */
61 	LTC_ARGCHK(key != NULL);
62 	LTC_ARGCHK(key->base != NULL);
63 	LTC_ARGCHK(key->prime != NULL);
64 	err = prng_is_valid(wprng);
65 	if (err != CRYPT_OK)
66 		return err;
67 
68 	/*
69 	 * Set the key size and check constraints
70 	 */
71 	if (xbits) {
72 		LTC_ARGCHK((xbits % 8) == 0);
73 		key_size = xbits / 8;
74 	}
75 	key_size_p = mp_unsigned_bin_size(key->prime);
76 	if (q)
77 		key_size_q = mp_unsigned_bin_size(q);
78 	if (key_size) {
79 		/* check the constraints */
80 		LTC_ARGCHK(key_size <= key_size_p);
81 		LTC_ARGCHK((q == NULL) || (key_size <= key_size_q));
82 	} else {
83 		if (q)
84 			key_size = MIN(key_size_p, key_size_q);
85 		else
86 			key_size =key_size_p;
87 	}
88 
89 	/* Set the argument we will make the modulo against to */
90 	if ((q != NULL) && (key_size_q < key_size_p))
91 		arg_mod = q;
92 	else
93 		arg_mod = key->prime;
94 
95 	/* initialize the key */
96 	key->x = NULL;
97 	key->y = NULL;
98 	err = mp_init_multi(&key->x, &key->y, NULL);
99 	if (err != CRYPT_OK)
100 		goto error;
101 
102 	/* Initialize the buffer used to store the random number */
103 	buf = XMALLOC(key_size);
104 	if (buf == NULL) {
105 		err = CRYPT_MEM;
106 		goto error;
107 	}
108 
109 	/* generate the private key in a raw-buffer */
110 	if (prng_descriptor[wprng]->read(buf, key_size, prng) !=
111 	    (unsigned long)key_size) {
112 		err = CRYPT_ERROR_READPRNG;
113 		goto error;
114 	}
115 
116 	/*
117 	 * Transform it as a Big Number compatible with p and q
118 	 */
119 	err = mp_read_unsigned_bin(key->y, buf, key_size);
120 	if (err != CRYPT_OK)
121 		goto error;
122 	err = mp_mod(key->y, arg_mod, key->x);
123 	if (err != CRYPT_OK)
124 		goto error;
125 
126 	/* generate the public key key->y */
127 	err = mp_exptmod(key->base, key->x, key->prime, key->y);
128 	if (err != CRYPT_OK)
129 		goto error;
130 
131 	/* no error */
132 	err = CRYPT_OK;
133 
134 error:
135 	if (err != CRYPT_OK)
136 		mp_clear_multi(key->x, key->y, NULL);
137 	if (buf)
138 		XFREE(buf);
139 
140 	return err;
141 }
142