summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authortb <>2024-11-08 22:03:29 +0000
committertb <>2024-11-08 22:03:29 +0000
commit6b42101493f1f270e3e232e576ceb26a05cede5f (patch)
tree1f231b14e5b71cd9d8f6a4e9080686d27596eb99 /src/lib
parent87e01b19e22b5aa813af998b149eb34fd96de895 (diff)
downloadopenbsd-6b42101493f1f270e3e232e576ceb26a05cede5f.tar.gz
openbsd-6b42101493f1f270e3e232e576ceb26a05cede5f.tar.bz2
openbsd-6b42101493f1f270e3e232e576ceb26a05cede5f.zip
Sweep over EC_KEY_copy()
This is a special snowflake. Its logic is such that it only overwrites things on the target that are available in the source. So if the source has no group (yes, that's possible), the destination's group will remain. Even better: if you copy a public key over what was previously a private key, the private scalar will remain. That's almost never going to result in a valid key. If you copy from a larger group to a smaller group the private scalar will most likely be out of range [1, order). Use dup functions instead of reimplementing badly and add a snarky comment courtesy of beck to one of those silly const annotations (there's a small addendum by me). ok beck jsing
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/ec/ec_key.c60
1 files changed, 28 insertions, 32 deletions
diff --git a/src/lib/libcrypto/ec/ec_key.c b/src/lib/libcrypto/ec/ec_key.c
index 753ababa31..4f3f27dabd 100644
--- a/src/lib/libcrypto/ec/ec_key.c
+++ b/src/lib/libcrypto/ec/ec_key.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_key.c,v 1.44 2024/11/08 21:56:58 tb Exp $ */ 1/* $OpenBSD: ec_key.c,v 1.45 2024/11/08 22:03:29 tb Exp $ */
2/* 2/*
3 * Written by Nils Larsch for the OpenSSL project. 3 * Written by Nils Larsch for the OpenSSL project.
4 */ 4 */
@@ -132,58 +132,54 @@ EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
132 ECerror(ERR_R_PASSED_NULL_PARAMETER); 132 ECerror(ERR_R_PASSED_NULL_PARAMETER);
133 return NULL; 133 return NULL;
134 } 134 }
135
135 if (src->meth != dest->meth) { 136 if (src->meth != dest->meth) {
136 if (dest->meth != NULL && dest->meth->finish != NULL) 137 if (dest->meth != NULL && dest->meth->finish != NULL)
137 dest->meth->finish(dest); 138 dest->meth->finish(dest);
138 } 139 }
139 /* copy the parameters */ 140
140 if (src->group) { 141 if (src->group != NULL) {
141 const EC_METHOD *meth = src->group->meth;
142 /* clear the old group */
143 EC_GROUP_free(dest->group); 142 EC_GROUP_free(dest->group);
144 dest->group = EC_GROUP_new(meth); 143 if ((dest->group = EC_GROUP_dup(src->group)) == NULL)
145 if (dest->group == NULL)
146 return NULL;
147 if (!EC_GROUP_copy(dest->group, src->group))
148 return NULL;
149 }
150 /* copy the public key */
151 if (src->pub_key && src->group) {
152 EC_POINT_free(dest->pub_key);
153 dest->pub_key = EC_POINT_new(src->group);
154 if (dest->pub_key == NULL)
155 return NULL; 144 return NULL;
156 if (!EC_POINT_copy(dest->pub_key, src->pub_key)) 145 if (src->pub_key != NULL) {
157 return NULL; 146 EC_POINT_free(dest->pub_key);
158 } 147 if ((dest->pub_key = EC_POINT_dup(src->pub_key,
159 /* copy the private key */ 148 src->group)) == NULL)
160 if (src->priv_key) {
161 if (dest->priv_key == NULL) {
162 dest->priv_key = BN_new();
163 if (dest->priv_key == NULL)
164 return NULL; 149 return NULL;
165 } 150 }
166 if (!bn_copy(dest->priv_key, src->priv_key)) 151 }
152
153 /*
154 * XXX - if there's no priv_key on src, dest retains its probably
155 * invalid priv_key. This makes no sense. Can we change this?
156 */
157 if (src->priv_key != NULL) {
158 BN_free(dest->priv_key);
159 if ((dest->priv_key = BN_dup(src->priv_key)) == NULL)
167 return NULL; 160 return NULL;
168 } 161 }
169 162
170 /* copy the rest */
171 dest->enc_flag = src->enc_flag; 163 dest->enc_flag = src->enc_flag;
172 dest->conv_form = src->conv_form; 164 dest->conv_form = src->conv_form;
173 dest->version = src->version; 165 dest->version = src->version;
174 dest->flags = src->flags; 166 dest->flags = src->flags;
175 167
168 /*
169 * The fun part about being a toolkit implementer is that the rest of
170 * the world gets to live with your terrible API design choices for
171 * eternity. (To be fair: the signature was changed in OpenSSL 3).
172 */
176 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY, &dest->ex_data, 173 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY, &dest->ex_data,
177 &((EC_KEY *)src)->ex_data)) /* XXX const */ 174 &((EC_KEY *)src)->ex_data)) /* XXX const */
178 return NULL; 175 return NULL;
179 176
180 if (src->meth != dest->meth) { 177 dest->meth = src->meth;
181 dest->meth = src->meth;
182 }
183 178
184 if (src->meth != NULL && src->meth->copy != NULL && 179 if (src->meth != NULL && src->meth->copy != NULL) {
185 src->meth->copy(dest, src) == 0) 180 if (!src->meth->copy(dest, src))
186 return 0; 181 return NULL;
182 }
187 183
188 return dest; 184 return dest;
189} 185}