Refactor TLS1-PRF to create the MAC contexts early
[openssl.git] / crypto / param_build.c
1 /*
2  * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
3  * Copyright (c) 2019, Oracle and/or its affiliates.  All rights reserved.
4  *
5  * Licensed under the Apache License 2.0 (the "License").  You may not use
6  * this file except in compliance with the License.  You can obtain a copy
7  * in the file LICENSE in the source distribution or at
8  * https://www.openssl.org/source/license.html
9  */
10
11 #include <string.h>
12 #include <openssl/err.h>
13 #include <openssl/cryptoerr.h>
14 #include <openssl/params.h>
15 #include "internal/cryptlib.h"
16 #include "internal/param_build.h"
17
18 #define OSSL_PARAM_ALLOCATED_END    127
19
20 typedef union {
21     OSSL_UNION_ALIGN;
22 } OSSL_PARAM_BLD_BLOCK;
23
24 #define ALIGN_SIZE  sizeof(OSSL_PARAM_BLD_BLOCK)
25
26 static size_t bytes_to_blocks(size_t bytes)
27 {
28     return (bytes + ALIGN_SIZE - 1) / ALIGN_SIZE;
29 }
30
31 static OSSL_PARAM_BLD_DEF *param_push(OSSL_PARAM_BLD *bld, const char *key,
32                                       int size, size_t alloc, int type,
33                                       int secure)
34 {
35     OSSL_PARAM_BLD_DEF *pd;
36
37     if (bld->curr >= OSSL_PARAM_BLD_MAX) {
38         CRYPTOerr(CRYPTO_F_PARAM_PUSH, CRYPTO_R_TOO_MANY_RECORDS);
39         return NULL;
40     }
41     pd = bld->params + bld->curr++;
42     memset(pd, 0, sizeof(*pd));
43     pd->key = key;
44     pd->type = type;
45     pd->size = size;
46     pd->alloc_blocks = bytes_to_blocks(size);
47     if ((pd->secure = secure) != 0)
48         bld->secure_blocks += pd->alloc_blocks;
49     else
50         bld->total_blocks += pd->alloc_blocks;
51     return pd;
52 }
53
54 static int param_push_num(OSSL_PARAM_BLD *bld, const char *key,
55                           void *num, size_t size, int type)
56 {
57     OSSL_PARAM_BLD_DEF *pd = param_push(bld, key, size, size, type, 0);
58
59     if (pd == NULL)
60         return 0;
61     if (size > sizeof(pd->num)) {
62         CRYPTOerr(CRYPTO_F_PARAM_PUSH_NUM, CRYPTO_R_TOO_MANY_BYTES);
63         return 0;
64     }
65     memcpy(&pd->num, num, size);
66     return 1;
67 }
68
69 void ossl_param_bld_init(OSSL_PARAM_BLD *bld)
70 {
71     memset(bld, 0, sizeof(*bld));
72 }
73
74 int ossl_param_bld_push_int(OSSL_PARAM_BLD *bld, const char *key, int num)
75 {
76     return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER);
77 }
78
79 int ossl_param_bld_push_uint(OSSL_PARAM_BLD *bld, const char *key,
80                              unsigned int num)
81 {
82     return param_push_num(bld, key, &num, sizeof(num),
83                           OSSL_PARAM_UNSIGNED_INTEGER);
84 }
85
86 int ossl_param_bld_push_long(OSSL_PARAM_BLD *bld, const char *key,
87                              long int num)
88 {
89     return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER);
90 }
91
92 int ossl_param_bld_push_ulong(OSSL_PARAM_BLD *bld, const char *key,
93                               unsigned long int num)
94 {
95     return param_push_num(bld, key, &num, sizeof(num),
96                           OSSL_PARAM_UNSIGNED_INTEGER);
97 }
98
99 int ossl_param_bld_push_int32(OSSL_PARAM_BLD *bld, const char *key,
100                               int32_t num)
101 {
102     return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER);
103 }
104
105 int ossl_param_bld_push_uint32(OSSL_PARAM_BLD *bld, const char *key,
106                                uint32_t num)
107 {
108     return param_push_num(bld, key, &num, sizeof(num),
109                           OSSL_PARAM_UNSIGNED_INTEGER);
110 }
111
112 int ossl_param_bld_push_int64(OSSL_PARAM_BLD *bld, const char *key,
113                               int64_t num)
114 {
115     return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_INTEGER);
116 }
117
118 int ossl_param_bld_push_uint64(OSSL_PARAM_BLD *bld, const char *key,
119                                uint64_t num)
120 {
121     return param_push_num(bld, key, &num, sizeof(num),
122                           OSSL_PARAM_UNSIGNED_INTEGER);
123 }
124
125 int ossl_param_bld_push_size_t(OSSL_PARAM_BLD *bld, const char *key,
126                                size_t num)
127 {
128     return param_push_num(bld, key, &num, sizeof(num),
129                           OSSL_PARAM_UNSIGNED_INTEGER);
130 }
131
132 int ossl_param_bld_push_double(OSSL_PARAM_BLD *bld, const char *key,
133                                double num)
134 {
135     return param_push_num(bld, key, &num, sizeof(num), OSSL_PARAM_REAL);
136 }
137
138 int ossl_param_bld_push_BN(OSSL_PARAM_BLD *bld, const char *key,
139                            const BIGNUM *bn)
140 {
141     int sz = -1, secure = 0;
142     OSSL_PARAM_BLD_DEF *pd;
143
144     if (bn != NULL) {
145         sz = BN_num_bytes(bn);
146         if (sz < 0) {
147             CRYPTOerr(CRYPTO_F_OSSL_PARAM_BLD_PUSH_BN,
148                       CRYPTO_R_ZERO_LENGTH_NUMBER);
149             return 0;
150         }
151         if (BN_get_flags(bn, BN_FLG_SECURE) == BN_FLG_SECURE)
152             secure = 1;
153     }
154     pd = param_push(bld, key, sz, sz >= 0 ? sz : 0,
155                     OSSL_PARAM_UNSIGNED_INTEGER, secure);
156     if (pd == NULL)
157         return 0;
158     pd->bn = bn;
159     return 1;
160 }
161
162 int ossl_param_bld_push_utf8_string(OSSL_PARAM_BLD *bld, const char *key,
163                                     const char *buf, size_t bsize)
164 {
165     OSSL_PARAM_BLD_DEF *pd;
166
167     if (bsize == 0) {
168         bsize = strlen(buf) + 1;
169     } else if (bsize > INT_MAX) {
170         CRYPTOerr(CRYPTO_F_OSSL_PARAM_BLD_PUSH_UTF8_STRING,
171                   CRYPTO_R_STRING_TOO_LONG);
172         return 0;
173     }
174     pd = param_push(bld, key, bsize, bsize, OSSL_PARAM_UTF8_STRING, 0);
175     if (pd == NULL)
176         return 0;
177     pd->string = buf;
178     return 1;
179 }
180
181 int ossl_param_bld_push_utf8_ptr(OSSL_PARAM_BLD *bld, const char *key,
182                                  char *buf, size_t bsize)
183 {
184     OSSL_PARAM_BLD_DEF *pd;
185
186     if (bsize == 0) {
187         bsize = strlen(buf) + 1;
188     } else if (bsize > INT_MAX) {
189         CRYPTOerr(CRYPTO_F_OSSL_PARAM_BLD_PUSH_UTF8_PTR,
190                   CRYPTO_R_STRING_TOO_LONG);
191         return 0;
192     }
193     pd = param_push(bld, key, bsize, sizeof(buf), OSSL_PARAM_UTF8_PTR, 0);
194     if (pd == NULL)
195         return 0;
196     pd->string = buf;
197     return 1;
198 }
199
200 int ossl_param_bld_push_octet_string(OSSL_PARAM_BLD *bld, const char *key,
201                                      const void *buf, size_t bsize)
202 {
203     OSSL_PARAM_BLD_DEF *pd;
204
205     if (bsize > INT_MAX) {
206         CRYPTOerr(CRYPTO_F_OSSL_PARAM_BLD_PUSH_OCTET_STRING,
207                   CRYPTO_R_STRING_TOO_LONG);
208         return 0;
209     }
210     pd = param_push(bld, key, bsize, bsize, OSSL_PARAM_OCTET_STRING, 0);
211     if (pd == NULL)
212         return 0;
213     pd->string = buf;
214     return 1;
215 }
216
217 int ossl_param_bld_push_octet_ptr(OSSL_PARAM_BLD *bld, const char *key,
218                                   void *buf, size_t bsize)
219 {
220     OSSL_PARAM_BLD_DEF *pd;
221
222     if (bsize > INT_MAX) {
223         CRYPTOerr(CRYPTO_F_OSSL_PARAM_BLD_PUSH_OCTET_PTR,
224                   CRYPTO_R_STRING_TOO_LONG);
225         return 0;
226     }
227     pd = param_push(bld, key, bsize, sizeof(buf), OSSL_PARAM_OCTET_PTR, 0);
228     if (pd == NULL)
229         return 0;
230     pd->string = buf;
231     return 1;
232 }
233
234 static OSSL_PARAM *param_bld_convert(OSSL_PARAM_BLD *bld, OSSL_PARAM *param,
235                                      OSSL_PARAM_BLD_BLOCK *blk,
236                                      OSSL_PARAM_BLD_BLOCK *secure)
237 {
238     size_t i;
239     OSSL_PARAM_BLD_DEF *pd;
240     void *p;
241
242     for (i = 0; i < bld->curr; i++) {
243         pd = bld->params + i;
244         param[i].key = pd->key;
245         param[i].data_type = pd->type;
246         param[i].data_size = pd->size;
247         param[i].return_size = 0;
248
249         if (pd->secure) {
250             p = secure;
251             secure += pd->alloc_blocks;
252         } else {
253             p = blk;
254             blk += pd->alloc_blocks;
255         }
256         param[i].data = p;
257         if (pd->bn != NULL) {
258             /* BIGNUM */
259             BN_bn2nativepad(pd->bn, (unsigned char *)p, pd->size);
260         } else if (pd->type == OSSL_PARAM_OCTET_PTR
261                    || pd->type == OSSL_PARAM_UTF8_PTR) {
262             /* PTR */
263             *(const void **)p = pd->string;
264         } else if (pd->type == OSSL_PARAM_OCTET_STRING
265                    || pd->type == OSSL_PARAM_UTF8_STRING) {
266             if (pd->string != NULL)
267                 memcpy(p, pd->string, pd->size);
268             else
269                 memset(p, 0, pd->size);
270         } else {
271             /* Number, but could also be a NULL BIGNUM */
272             if (pd->size > sizeof(pd->num))
273                 memset(p, 0, pd->size);
274             else if (pd->size > 0)
275                 memcpy(p, &pd->num, pd->size);
276         }
277     }
278     param[i] = OSSL_PARAM_construct_end();
279     return param + i;
280 }
281
282 OSSL_PARAM *ossl_param_bld_to_param(OSSL_PARAM_BLD *bld)
283 {
284     OSSL_PARAM_BLD_BLOCK *blk, *s = NULL;
285     OSSL_PARAM *params, *last;
286     const size_t p_blks = bytes_to_blocks((1 + bld->curr) * sizeof(*params));
287     const size_t total = ALIGN_SIZE * (p_blks + bld->total_blocks);
288     const size_t ss = ALIGN_SIZE * bld->secure_blocks;
289
290     if (ss > 0) {
291         s = OPENSSL_secure_malloc(ss);
292         if (s == NULL) {
293             CRYPTOerr(CRYPTO_F_OSSL_PARAM_BLD_TO_PARAM,
294                       CRYPTO_R_SECURE_MALLOC_FAILURE);
295             return NULL;
296         }
297     }
298     params = OPENSSL_malloc(total);
299     if (params == NULL) {
300         CRYPTOerr(CRYPTO_F_OSSL_PARAM_BLD_TO_PARAM, ERR_R_MALLOC_FAILURE);
301         OPENSSL_secure_free(s);
302         return NULL;
303     }
304     blk = p_blks + (OSSL_PARAM_BLD_BLOCK *)(params);
305     last = param_bld_convert(bld, params, blk, s);
306     last->data_size = ss;
307     last->data = s;
308     last->data_type = OSSL_PARAM_ALLOCATED_END;
309     return params;
310 }
311
312 void ossl_param_bld_free(OSSL_PARAM *params)
313 {
314     if (params != NULL) {
315         OSSL_PARAM *p;
316
317         for (p = params; p->key != NULL; p++)
318             ;
319         if (p->data_type == OSSL_PARAM_ALLOCATED_END)
320             OPENSSL_secure_clear_free(p->data, p->data_size);
321         OPENSSL_free(params);
322     }
323 }
324
325 OSSL_PARAM *ossl_param_bld_to_param_ex(OSSL_PARAM_BLD *bld, OSSL_PARAM *params,
326                                        size_t param_n, void *data,
327                                        size_t data_n, void *secure,
328                                        size_t secure_n)
329 {
330     if (params == NULL || data == NULL) {
331         CRYPTOerr(CRYPTO_F_OSSL_PARAM_BLD_TO_PARAM_EX,
332                   CRYPTO_R_INVALID_NULL_ARGUMENT);
333         return NULL;
334     }
335     if (param_n < bld->curr + 1) {
336         CRYPTOerr(CRYPTO_F_OSSL_PARAM_BLD_TO_PARAM_EX,
337                   CRYPTO_R_INSUFFICIENT_PARAM_SIZE);
338         return NULL;
339     }
340     if (data_n < ALIGN_SIZE * bld->total_blocks) {
341         CRYPTOerr(CRYPTO_F_OSSL_PARAM_BLD_TO_PARAM_EX,
342                   CRYPTO_R_INSUFFICIENT_DATA_SPACE);
343         return NULL;
344     }
345     if (bld->secure_blocks > 0 && secure_n < ALIGN_SIZE * bld->secure_blocks) {
346         CRYPTOerr(CRYPTO_F_OSSL_PARAM_BLD_TO_PARAM_EX,
347                   CRYPTO_R_INSUFFICIENT_SECURE_DATA_SPACE);
348         return NULL;
349     }
350     param_bld_convert(bld, params, (OSSL_PARAM_BLD_BLOCK *)data,
351                       (OSSL_PARAM_BLD_BLOCK *)secure);
352     return params;
353 }