Coverage Report

Created: 2026-09-14 06:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/openpace/src/misc.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2010-2012 Frank Morgner and Dominik Oepen
3
 *
4
 * This file is part of OpenPACE.
5
 *
6
 * OpenPACE is free software: you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free
8
 * Software Foundation, either version 3 of the License, or (at your option)
9
 * any later version.
10
 *
11
 * OpenPACE is distributed in the hope that it will be useful, but WITHOUT ANY
12
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * OpenPACE.  If not, see <http://www.gnu.org/licenses/>.
18
 *
19
 * Additional permission under GNU GPL version 3 section 7
20
 *
21
 * If you modify this Program, or any covered work, by linking or combining it
22
 * with OpenSSL (or a modified version of that library), containing
23
 * parts covered by the terms of OpenSSL's license, the licensors of
24
 * this Program grant you additional permission to convey the resulting work.
25
 * Corresponding Source for a non-source form of such a combination shall include
26
 * the source code for the parts of OpenSSL used as well as that of the
27
 * covered work.
28
 *
29
 * If you modify this Program, or any covered work, by linking or combining it
30
 * with OpenSC (or a modified version of that library), containing
31
 * parts covered by the terms of OpenSC's license, the licensors of
32
 * this Program grant you additional permission to convey the resulting work. 
33
 * Corresponding Source for a non-source form of such a combination shall include
34
 * the source code for the parts of OpenSC used as well as that of the
35
 * covered work.
36
 */
37
38
/**
39
 * @file misc.c
40
 * @brief Miscellaneous functions used in OpenPACE
41
 *
42
 * @author Frank Morgner <frankmorgner@gmail.com>
43
 * @author Dominik Oepen <oepen@informatik.hu-berlin.de>
44
 */
45
46
#ifdef HAVE_CONFIG_H
47
#include "config.h"
48
#endif
49
50
#include "eac_err.h"
51
#include "misc.h"
52
#include <limits.h>
53
#include <openssl/ecdh.h>
54
#include <openssl/ecdsa.h>
55
#include <openssl/ossl_typ.h>
56
#include <stdint.h>
57
#include <string.h>
58
59
static int ecdh_compute_key_point(void *out, size_t outlen, const EC_POINT *pub_key,
60
        EC_KEY *ecdh,
61
        void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen));
62
static int new_ecdh_compute_key_point(unsigned char **psec, size_t *pseclen,
63
        const EC_POINT *pub_key, const EC_KEY *ecdh);
64
65
struct ec_key_method_st {
66
    const char *name;
67
    int32_t flags;
68
    int (*init)(EC_KEY *key);
69
    void (*finish)(EC_KEY *key);
70
    int (*copy)(EC_KEY *dest, const EC_KEY *src);
71
    int (*set_group)(EC_KEY *key, const EC_GROUP *grp);
72
    int (*set_private)(EC_KEY *key, const BIGNUM *priv_key);
73
    int (*set_public)(EC_KEY *key, const EC_POINT *pub_key);
74
    int (*keygen)(EC_KEY *key);
75
    int (*compute_key)(unsigned char **pout, size_t *poutlen,
76
            const EC_POINT *pub_key, const EC_KEY *ecdh);
77
    int (*sign)(int type, const unsigned char *dgst, int dlen, unsigned char
78
            *sig, unsigned int *siglen, const BIGNUM *kinv,
79
            const BIGNUM *r, EC_KEY *eckey);
80
    int (*sign_setup)(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
81
            BIGNUM **rp);
82
    ECDSA_SIG *(*sign_sig)(const unsigned char *dgst, int dgst_len,
83
            const BIGNUM *in_kinv, const BIGNUM *in_r,
84
            EC_KEY *eckey);
85
86
    int (*verify)(int type, const unsigned char *dgst, int dgst_len,
87
            const unsigned char *sigbuf, int sig_len, EC_KEY *eckey);
88
    int (*verify_sig)(const unsigned char *dgst, int dgst_len,
89
            const ECDSA_SIG *sig, EC_KEY *eckey);
90
};
91
92
struct ecdh_method
93
{
94
    const char *name;
95
    int (*compute_key)(void *key, size_t outlen, const EC_POINT *pub_key, EC_KEY *ecdh,
96
            void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen));
97
#if 0
98
    int (*init)(EC_KEY *eckey);
99
    int (*finish)(EC_KEY *eckey);
100
#endif
101
    int flags;
102
    char *app_data;
103
};
104
105
#ifdef HAVE_EC_KEY_METHOD
106
107
static const EC_KEY_METHOD openssl_ec_key_meth_point = {
108
    "OpenSSL EC_KEY method with Point",
109
    0,
110
    0,0,0,0,0,0,
111
    NULL,
112
    new_ecdh_compute_key_point,
113
    NULL,
114
    NULL,
115
    NULL,
116
    NULL,
117
    NULL
118
};
119
120
const EC_KEY_METHOD *EC_KEY_OpenSSL_Point(void)
121
0
{
122
0
    return &openssl_ec_key_meth_point;
123
0
}
124
125
#else
126
127
static ECDH_METHOD openssl_ecdh_meth_point = {
128
    "OpenSSL ECDH method with Point",
129
    ecdh_compute_key_point,
130
#if 0
131
    NULL, /* init   */
132
    NULL, /* finish */
133
#endif
134
    0,    /* flags  */
135
    NULL  /* app_data */
136
};
137
138
const ECDH_METHOD *ECDH_OpenSSL_Point(void)
139
{
140
    return &openssl_ecdh_meth_point;
141
}
142
#endif
143
144
int new_ecdh_compute_key_point(unsigned char **psec, size_t *pseclen, const
145
        EC_POINT *pub_key, const EC_KEY *ecdh)
146
0
{
147
    /* The new API requires us to allocate the memory for the output buffer */
148
0
    int ret= -1;
149
    /* should be enough to hold an uncompressed point of a 528 bit curve
150
     * (e.g. secp521r1, which is the biggest curve of BSI TR-03110) */
151
0
    *psec = OPENSSL_malloc(133);
152
0
    check(*psec, "Out of memory");
153
0
    *pseclen = 133;
154
0
    ret = ecdh_compute_key_point(*psec, *pseclen, pub_key, (EC_KEY *) ecdh, NULL);
155
0
err:
156
0
    if (ret <= 0) {
157
0
        OPENSSL_free(*psec);
158
0
        *psec = NULL;
159
0
        *pseclen = 0;
160
0
        ret = 0;
161
0
    } else {
162
0
        *pseclen = ret;
163
0
        ret = 1;
164
0
    }
165
0
    return ret;
166
0
}
167
168
int ecdh_compute_key_point(void *out, size_t outlen, const EC_POINT *pub_key,
169
        EC_KEY *ecdh,
170
        void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen))
171
0
{
172
    /* The old API allocates the memory for us */
173
0
    BN_CTX *ctx = NULL;
174
0
    EC_POINT *tmp=NULL;
175
0
    const BIGNUM *priv_key;
176
0
    const EC_GROUP* group;
177
0
    int ret= -1;
178
0
    size_t buflen;
179
0
    unsigned char *buf=NULL;
180
181
0
    check((outlen < INT_MAX), "out of memory"); /* sort of, anyway */
182
183
0
    if ((ctx = BN_CTX_new()) == NULL) goto err;
184
0
    BN_CTX_start(ctx);
185
186
0
    priv_key = EC_KEY_get0_private_key(ecdh);
187
0
    check(priv_key, "No pivate key");
188
189
0
    group = EC_KEY_get0_group(ecdh);
190
0
    tmp = EC_POINT_new(group);
191
0
    check(tmp, "Out of memory");
192
193
0
    check((EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)),
194
0
            "Arithmetic error");
195
196
0
    buflen = EC_POINT_point2oct(group, tmp, EC_KEY_get_conv_form(ecdh), NULL,
197
0
            0, ctx);
198
0
    check((buflen != 0), "Failed to convert point to hex");
199
200
0
    buf = OPENSSL_malloc(buflen);
201
0
    check(buf, "Out of memory");
202
203
0
    check((buflen == EC_POINT_point2oct(group, tmp, EC_KEY_get_conv_form(ecdh),
204
0
                    buf, buflen, ctx)), "Failed to convert point to hex");
205
206
0
    if (KDF != 0)
207
0
    {
208
0
        check((KDF(buf, buflen, out, &outlen) != NULL),
209
0
                "Key derivation function failed");
210
0
        ret = outlen;
211
0
    }
212
0
    else
213
0
    {
214
        /* no KDF, just copy as much as we can */
215
0
        if (outlen > buflen)
216
0
            outlen = buflen;
217
0
        memcpy(out, buf, outlen);
218
0
        ret = outlen;
219
0
    }
220
221
0
err:
222
0
    if (tmp) EC_POINT_free(tmp);
223
0
    if (ctx) BN_CTX_end(ctx);
224
0
    if (ctx) BN_CTX_free(ctx);
225
0
    if (buf) OPENSSL_free(buf);
226
0
    return(ret);
227
0
}
228
229
BUF_MEM *
230
BUF_MEM_create(size_t len)
231
0
{
232
0
    BUF_MEM *out = BUF_MEM_new();
233
0
    if (!out)
234
0
        return NULL;
235
236
0
    if (len == 0)
237
0
        return out;
238
239
0
    if (!BUF_MEM_grow(out, len)) {
240
0
        BUF_MEM_free(out);
241
0
        return NULL;
242
0
    }
243
244
0
    return out;
245
0
}
246
247
BUF_MEM *
248
BUF_MEM_create_init(const void *buf, size_t len)
249
0
{
250
0
    BUF_MEM *out;
251
252
0
    out = BUF_MEM_create(len);
253
0
    if (!out)
254
0
        return NULL;
255
256
0
    memcpy(out->data, buf, len);
257
258
0
    return out;
259
0
}
260
261
BUF_MEM *
262
BUF_MEM_dup(const BUF_MEM * in)
263
0
{
264
0
    BUF_MEM * out = NULL;
265
266
0
    if (!in)
267
0
        return NULL;
268
269
0
    out = BUF_MEM_create(in->length);
270
0
    check(out, "Failed to allocate memory");
271
272
0
    memcpy(out->data, in->data, in->length);
273
0
    out->max = in->max;
274
275
0
err:
276
0
    return out;
277
0
}
278
279
BUF_MEM *
280
BN_bn2buf(const BIGNUM *bn)
281
0
{
282
0
    BUF_MEM * out;
283
284
0
    if (!bn)
285
0
        return NULL;
286
287
0
    out = BUF_MEM_create(BN_num_bytes(bn));
288
0
    if (!out)
289
0
        return NULL;
290
291
0
    out->length = BN_bn2bin(bn, (unsigned char *) out->data);
292
293
0
    return out;
294
0
}
295
296
BUF_MEM *
297
EC_POINT_point2mem(const EC_KEY * ecdh, BN_CTX * bn_ctx, const EC_POINT * ecp)
298
0
{
299
0
    size_t len;
300
0
    BUF_MEM * out;
301
302
0
    if (!ecp)
303
0
        return NULL;
304
305
0
    len = EC_POINT_point2oct(EC_KEY_get0_group(ecdh), ecp,
306
0
            EC_KEY_get_conv_form(ecdh), NULL, 0, bn_ctx);
307
0
    if (len == 0)
308
0
        return NULL;
309
310
0
    out = BUF_MEM_create(len);
311
0
    if (!out)
312
0
        return NULL;
313
314
0
    out->length = EC_POINT_point2oct(EC_KEY_get0_group(ecdh), ecp,
315
0
            EC_KEY_get_conv_form(ecdh), (unsigned char *) out->data, out->max,
316
0
            bn_ctx);
317
318
0
    return out;
319
0
}