]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/params_from_text.c
Params: add argument to the _from_text calls to indicate if the param exists.
[thirdparty/openssl.git] / crypto / params_from_text.c
CommitLineData
246a1f3d
RL
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/params.h>
14
15/*
16 * When processing text to params, we're trying to be smart with numbers.
17 * Instead of handling each specific separate integer type, we use a bignum
18 * and ensure that it isn't larger than the expected size, and we then make
19 * sure it is the expected size... if there is one given.
20 * (if the size can be arbitrary, then we give whatever we have)
21 */
22
23static int prepare_from_text(const OSSL_PARAM *paramdefs, const char *key,
24 const char *value, size_t value_n,
25 /* Output parameters */
26 const OSSL_PARAM **paramdef, int *ishex,
2ee0dfa6 27 size_t *buf_n, BIGNUM **tmpbn, int *found)
246a1f3d
RL
28{
29 const OSSL_PARAM *p;
30
31 /*
32 * ishex is used to translate legacy style string controls in hex format
33 * to octet string parameters.
34 */
35 *ishex = strncmp(key, "hex", 3) == 0;
36
37 if (*ishex)
38 key += 3;
39
40 p = *paramdef = OSSL_PARAM_locate_const(paramdefs, key);
2ee0dfa6
P
41 if (found != NULL)
42 *found = p != NULL;
246a1f3d
RL
43 if (p == NULL)
44 return 0;
45
46 switch (p->data_type) {
47 case OSSL_PARAM_INTEGER:
48 case OSSL_PARAM_UNSIGNED_INTEGER:
49 if (*ishex)
50 BN_hex2bn(tmpbn, value);
51 else
52 BN_dec2bn(tmpbn, value);
53
54 if (*tmpbn == NULL)
55 return 0;
56
57 /*
58 * 2s complement negate, part 1
59 *
60 * BN_bn2nativepad puts the absolute value of the number in the
61 * buffer, i.e. if it's negative, we need to deal with it. We do
62 * it by subtracting 1 here and inverting the bytes in
63 * construct_from_text() below.
64 */
65 if (p->data_type == OSSL_PARAM_INTEGER && BN_is_negative(*tmpbn)
66 && !BN_sub_word(*tmpbn, 1)) {
67 return 0;
68 }
69
70 *buf_n = BN_num_bytes(*tmpbn);
71
72 /*
73 * TODO(v3.0) is this the right way to do this? This code expects
74 * a zero data size to simply mean "arbitrary size".
75 */
76 if (p->data_size > 0) {
77 if (*buf_n >= p->data_size) {
78 CRYPTOerr(0, CRYPTO_R_TOO_SMALL_BUFFER);
79 /* Since this is a different error, we don't break */
80 return 0;
81 }
82 /* Change actual size to become the desired size. */
83 *buf_n = p->data_size;
84 }
85 break;
86 case OSSL_PARAM_UTF8_STRING:
87 if (*ishex) {
88 CRYPTOerr(0, ERR_R_PASSED_INVALID_ARGUMENT);
89 return 0;
90 }
91 *buf_n = strlen(value) + 1;
92 break;
93 case OSSL_PARAM_OCTET_STRING:
94 if (*ishex) {
95 *buf_n = strlen(value) >> 1;
810a1d03
RL
96 } else {
97 *buf_n = value_n;
246a1f3d
RL
98 }
99 break;
100 }
101
102 return 1;
103}
104
105static int construct_from_text(OSSL_PARAM *to, const OSSL_PARAM *paramdef,
106 const char *value, size_t value_n, int ishex,
107 void *buf, size_t buf_n, BIGNUM *tmpbn)
108{
109 if (buf == NULL)
110 return 0;
111
9d8e1569
P
112 if (buf_n > 0) {
113 switch (paramdef->data_type) {
114 case OSSL_PARAM_INTEGER:
115 case OSSL_PARAM_UNSIGNED_INTEGER:
116 /*
117 {
118 if ((new_value = OPENSSL_malloc(new_value_n)) == NULL) {
119 BN_free(a);
120 break;
121 }
122 */
123
124 BN_bn2nativepad(tmpbn, buf, buf_n);
125
126 /*
127 * 2s complement negate, part two.
128 *
129 * Because we did the first part on the BIGNUM itself, we can just
130 * invert all the bytes here and be done with it.
131 */
132 if (paramdef->data_type == OSSL_PARAM_INTEGER
133 && BN_is_negative(tmpbn)) {
134 unsigned char *cp;
135 size_t i = buf_n;
136
137 for (cp = buf; i-- > 0; cp++)
138 *cp ^= 0xFF;
246a1f3d 139 }
9d8e1569
P
140 break;
141 case OSSL_PARAM_UTF8_STRING:
142 strncpy(buf, value, buf_n);
143 break;
144 case OSSL_PARAM_OCTET_STRING:
145 if (ishex) {
146 size_t l = 0;
147
148 if (!OPENSSL_hexstr2buf_ex(buf, buf_n, &l, value))
149 return 0;
150 } else {
151 memcpy(buf, value, buf_n);
152 }
153 break;
246a1f3d 154 }
246a1f3d
RL
155 }
156
157 *to = *paramdef;
158 to->data = buf;
159 to->data_size = buf_n;
160 to->return_size = 0;
161
162 return 1;
163}
164
246a1f3d
RL
165int OSSL_PARAM_allocate_from_text(OSSL_PARAM *to,
166 const OSSL_PARAM *paramdefs,
167 const char *key, const char *value,
2ee0dfa6 168 size_t value_n, int *found)
246a1f3d
RL
169{
170 const OSSL_PARAM *paramdef = NULL;
171 int ishex = 0;
172 void *buf = NULL;
173 size_t buf_n = 0;
174 BIGNUM *tmpbn = NULL;
175 int ok = 0;
176
177 if (to == NULL || paramdefs == NULL)
178 return 0;
179
180 if (!prepare_from_text(paramdefs, key, value, value_n,
2ee0dfa6 181 &paramdef, &ishex, &buf_n, &tmpbn, found))
246a1f3d
RL
182 return 0;
183
9d8e1569 184 if ((buf = OPENSSL_zalloc(buf_n > 0 ? buf_n : 1)) == NULL) {
246a1f3d
RL
185 CRYPTOerr(0, ERR_R_MALLOC_FAILURE);
186 return 0;
187 }
188
189 ok = construct_from_text(to, paramdef, value, value_n, ishex,
190 buf, buf_n, tmpbn);
191 BN_free(tmpbn);
9d8e1569
P
192 if (!ok)
193 OPENSSL_free(buf);
246a1f3d
RL
194 return ok;
195}