Coverage Report

Created: 2026-06-10 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/openpace/src/pace.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 pace.c
40
 * @brief OpenPACE implementation
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 "eac_kdf.h"
52
#include "eac_lib.h"
53
#include "eac_util.h"
54
#include "misc.h"
55
#include "pace_mappings.h"
56
#include <eac/eac.h>
57
#include <eac/pace.h>
58
#include <openssl/crypto.h>
59
#include <openssl/ecdh.h>
60
#include <openssl/evp.h>
61
#include <openssl/objects.h>
62
#include <string.h>
63
64
BUF_MEM *
65
PACE_STEP1_enc_nonce(const EAC_CTX * ctx, const PACE_SEC * pi)
66
0
{
67
0
    BUF_MEM * enc_nonce = NULL;
68
0
    BUF_MEM * key = NULL;
69
70
0
    check((ctx && ctx->pace_ctx && ctx->pace_ctx->ka_ctx &&
71
0
                ctx->pace_ctx->ka_ctx->cipher),
72
0
            "Invalid arguments");
73
74
0
    key = kdf_pi(pi, NULL, ctx->pace_ctx->ka_ctx, ctx->md_ctx);
75
0
    check(key, "Key derivation function failed");
76
77
0
    BUF_MEM_clear_free(ctx->pace_ctx->nonce);
78
0
    ctx->pace_ctx->nonce = randb(EVP_CIPHER_block_size(ctx->pace_ctx->ka_ctx->cipher));
79
0
    check(ctx->pace_ctx->nonce, "Failed to create nonce");
80
81
0
    enc_nonce = cipher_no_pad(ctx->pace_ctx->ka_ctx, ctx->cipher_ctx, key, ctx->pace_ctx->nonce, 1);
82
83
0
err:
84
0
    BUF_MEM_clear_free(key);
85
86
0
    return enc_nonce;
87
0
}
88
89
int
90
PACE_STEP2_dec_nonce(const EAC_CTX * ctx, const PACE_SEC * pi,
91
        const BUF_MEM * enc_nonce)
92
0
{
93
0
    BUF_MEM *key = NULL;
94
0
    int r = 0;
95
96
0
    check((ctx && ctx->pace_ctx && ctx->pace_ctx->ka_ctx && ctx->pace_ctx->ka_ctx->cipher),
97
0
        "Invalid arguments");
98
99
0
    key = kdf_pi(pi, NULL, ctx->pace_ctx->ka_ctx, ctx->md_ctx);
100
0
    check(key, "Key derivation function failed");
101
102
0
    BUF_MEM_clear_free(ctx->pace_ctx->nonce);
103
0
    ctx->pace_ctx->nonce = cipher_no_pad(ctx->pace_ctx->ka_ctx, ctx->cipher_ctx, key, enc_nonce, 0);
104
0
    check(ctx->pace_ctx->nonce, "Failed to decrypt nonce");
105
106
0
    r = 1;
107
108
0
err:
109
0
    BUF_MEM_clear_free(key);
110
111
0
    return r;
112
0
}
113
114
BUF_MEM *
115
PACE_STEP3A_generate_mapping_data(const EAC_CTX * ctx)
116
0
{
117
0
    check_return((ctx && ctx->pace_ctx && ctx->pace_ctx->map_generate_key), "Invalid arguments");
118
119
0
    return ctx->pace_ctx->map_generate_key(ctx->pace_ctx, ctx->bn_ctx);
120
0
}
121
122
int
123
PACE_STEP3A_map_generator(const EAC_CTX * ctx, const BUF_MEM * in)
124
0
{
125
0
    if(!ctx || !ctx->pace_ctx || !ctx->pace_ctx->map_compute_key) {
126
0
        log_err("Invalid arguments");
127
0
        return 0;
128
0
    }
129
130
0
    return ctx->pace_ctx->map_compute_key(ctx->pace_ctx, ctx->pace_ctx->nonce, in, ctx->bn_ctx);
131
0
}
132
133
BUF_MEM *
134
PACE_STEP3B_generate_ephemeral_key(EAC_CTX * ctx)
135
0
{
136
0
    check_return((ctx && ctx->pace_ctx), "Invalid arguments");
137
138
0
    ctx->pace_ctx->my_eph_pubkey = KA_CTX_generate_key(ctx->pace_ctx->ka_ctx,
139
0
            ctx->bn_ctx);
140
141
0
    if (!ctx->pace_ctx->my_eph_pubkey)
142
0
        return NULL;
143
144
0
    return BUF_MEM_create_init(ctx->pace_ctx->my_eph_pubkey->data,
145
0
            ctx->pace_ctx->my_eph_pubkey->length);
146
0
}
147
148
int
149
PACE_STEP3B_compute_shared_secret(const EAC_CTX * ctx, const BUF_MEM * in)
150
0
{
151
0
    int r = 0;
152
153
0
    check((ctx  && ctx->pace_ctx  && ctx->pace_ctx->ka_ctx
154
0
            && ctx->pace_ctx->ka_ctx->compute_key && in), "Invalid arguments");
155
156
    /* Check if the new public key is different from the other party's public
157
     * key.  Note that this check is only required since TR-03110 v2.02, but it
158
     * makes sense to always check this... */
159
0
    if (!ctx->pace_ctx->my_eph_pubkey
160
0
               || (in->length == ctx->pace_ctx->my_eph_pubkey->length
161
0
                && memcmp(in->data, ctx->pace_ctx->my_eph_pubkey->data,
162
0
                    in->length) == 0)) {
163
0
        log_err("Bad DH or ECKEY object");
164
0
        goto err;
165
0
    }
166
167
168
0
    check(KA_CTX_compute_key(ctx->pace_ctx->ka_ctx, in, ctx->bn_ctx),
169
0
            "Failed to compute shared secret");
170
171
0
    r = 1;
172
173
0
err:
174
0
    return r;
175
0
}
176
177
int
178
PACE_STEP3C_derive_keys(const EAC_CTX *ctx)
179
0
{
180
0
    if (!ctx || !ctx->pace_ctx) {
181
0
        log_err("Invalid arguments");
182
0
        return 0;
183
0
    }
184
185
0
    return KA_CTX_derive_keys(ctx->pace_ctx->ka_ctx, NULL, ctx->md_ctx);
186
0
}
187
188
BUF_MEM *
189
PACE_STEP3D_compute_authentication_token(const EAC_CTX *ctx, const BUF_MEM *pub)
190
0
{
191
0
    if (!ctx || !ctx->pace_ctx) {
192
0
        log_err("Invalid arguments");
193
0
        return NULL;
194
0
    }
195
196
0
    return get_authentication_token(ctx->pace_ctx->protocol,
197
0
            ctx->pace_ctx->ka_ctx, ctx->bn_ctx,
198
0
            ctx->tr_version, pub);
199
0
}
200
201
int
202
PACE_STEP3D_verify_authentication_token(const EAC_CTX *ctx, const BUF_MEM *token)
203
0
{
204
0
    if (!ctx || !token|| !ctx->pace_ctx) {
205
0
        log_err("Invalid arguments");
206
0
        return -1;
207
0
    }
208
209
0
    return verify_authentication_token(ctx->pace_ctx->protocol,
210
0
            ctx->pace_ctx->ka_ctx, ctx->bn_ctx, ctx->tr_version,
211
0
            token);
212
0
}