Coverage Report

Created: 2025-11-24 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/openpace/src/ta.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 ta.c
40
 * @brief Protocol steps for the terminal authentication version 2
41
 *
42
 * @date 2011-04-03
43
 *
44
 * @author Frank Morgner <frankmorgner@gmail.com>
45
 * @author Dominik Oepen <oepen@informatik.hu-berlin.de>
46
 */
47
48
#ifdef HAVE_CONFIG_H
49
#include "config.h"
50
#endif
51
52
#include "eac_err.h"
53
#include "eac_lib.h"
54
#include "eac_util.h"
55
#include "misc.h"
56
#include "ta_lib.h"
57
#include <eac/cv_cert.h>
58
#include <eac/ta.h>
59
#include <openssl/bio.h>
60
#include <openssl/ecdsa.h>
61
#include <openssl/evp.h>
62
#include <openssl/rsa.h>
63
#include <string.h>
64
65
void TA_disable_checks(EAC_CTX *ctx)
66
0
{
67
0
    if (ctx && ctx->ta_ctx)
68
0
        ctx->ta_ctx->flags = TA_FLAG_SKIP_TIMECHECK;
69
0
}
70
71
int
72
TA_STEP2_import_certificate(const EAC_CTX *ctx,
73
           const unsigned char *cert, size_t cert_len)
74
0
{
75
0
    CVC_CERT *ta_cert = NULL;
76
0
    int r = 0;
77
78
0
    check(ctx, "Invalid arguments");
79
80
0
    ta_cert = CVC_d2i_CVC_CERT(&ta_cert, &cert, cert_len);
81
0
    r = TA_CTX_import_certificate(ctx->ta_ctx, ta_cert, ctx->bn_ctx);
82
83
0
err:
84
0
    if (ta_cert)
85
0
        CVC_CERT_free(ta_cert);
86
87
0
    return r;
88
0
}
89
90
/**
91
 * @brief gets the data, which is signed in the process of TA
92
 *
93
 * @param[in] pcd_ta_comp_eph_pubkey compressed ephemeral CA public key of PCD
94
 * @param[in] id_picc compressed ephemeral PACE public key of PICC
95
 * @param[in] nonce nonce from PICC
96
 * @param[in] (optional) auxdata auxiliary data from PCD
97
 *
98
 * @return A buffer containing the data to be signed or NULL in case of an error
99
 */
100
static BUF_MEM *
101
get_ta_sigdata(const BUF_MEM *pcd_ta_comp_eph_pubkey,
102
        const BUF_MEM *id_picc, const BUF_MEM *nonce,
103
        const BUF_MEM *auxdata)
104
0
{
105
0
    size_t len;
106
0
    BUF_MEM *data = NULL;
107
108
0
    check_return(nonce && pcd_ta_comp_eph_pubkey, "Invalid arguments");
109
110
    /* Data to be signed: ID PICC || r PICC || Comp(~PK_PCD) || APCD */
111
112
    /* Authenticated auxiliary data are optional (only necessary if special
113
     * functions will be used later on) */
114
0
    if (auxdata) {
115
0
        len = id_picc->length + nonce->length +
116
0
            pcd_ta_comp_eph_pubkey->length + auxdata->length;
117
0
    } else {
118
0
        len = id_picc->length + nonce->length +
119
0
            pcd_ta_comp_eph_pubkey->length;
120
0
    }
121
0
    data = BUF_MEM_create(len);
122
0
    if (!data)
123
0
        return NULL;
124
125
    /* Concatenate the data */
126
0
    memcpy(data->data, id_picc->data, id_picc->length);
127
0
    memcpy(data->data + id_picc->length, nonce->data, nonce->length);
128
0
    memcpy(data->data + id_picc->length + nonce->length, pcd_ta_comp_eph_pubkey->data,
129
0
            pcd_ta_comp_eph_pubkey->length);
130
0
    if (auxdata)
131
0
        memcpy(data->data + id_picc->length + nonce->length +
132
0
                pcd_ta_comp_eph_pubkey->length, auxdata->data, auxdata->length);
133
134
0
    return data;
135
0
}
136
137
BUF_MEM *
138
TA_STEP3_generate_ephemeral_key(const EAC_CTX *ctx)
139
0
{
140
0
    BUF_MEM *comp_pub_key, *pub_key = NULL;
141
142
0
    check_return(ctx && ctx->ca_ctx && ctx->ca_ctx->ka_ctx,
143
0
            "Invalid arguments");
144
145
0
    pub_key = KA_CTX_generate_key(ctx->ca_ctx->ka_ctx, ctx->bn_ctx);
146
147
0
    comp_pub_key = Comp(ctx->ca_ctx->ka_ctx->key, pub_key, ctx->bn_ctx,
148
0
            ctx->md_ctx);
149
150
0
    if (pub_key)
151
0
        BUF_MEM_free(pub_key);
152
153
0
    return comp_pub_key;
154
0
}
155
156
/* Nonce for TA is always 8 bytes long */
157
0
#define TA_NONCE_SIZE 8
158
BUF_MEM *
159
TA_STEP4_get_nonce(const EAC_CTX *ctx)
160
0
{
161
0
    check_return(ctx && ctx->ta_ctx, "Invalid arguments");
162
163
0
    BUF_MEM_clear_free(ctx->ta_ctx->nonce);
164
0
    ctx->ta_ctx->nonce = randb(TA_NONCE_SIZE);
165
166
0
    check_return(ctx->ta_ctx->nonce, "Failed to generate nonce");
167
168
0
    return BUF_MEM_dup(ctx->ta_ctx->nonce);
169
0
}
170
171
int
172
0
TA_STEP4_set_nonce(const EAC_CTX *ctx, const BUF_MEM *nonce) {
173
0
    int r = 0;
174
175
0
    check(ctx && ctx->ta_ctx && nonce, "Invalid arguments");
176
177
0
    if (ctx->ta_ctx->nonce)
178
0
      BUF_MEM_free(ctx->ta_ctx->nonce);
179
180
0
    ctx->ta_ctx->nonce = BUF_MEM_dup(nonce);
181
0
    check(ctx->ta_ctx->nonce, "Failed to copy nonce");
182
183
0
    r = 1;
184
0
err:
185
0
    return r;
186
0
}
187
188
BUF_MEM *
189
TA_STEP5_sign(const EAC_CTX *ctx, const BUF_MEM *my_ta_comp_eph_pubkey,
190
           const BUF_MEM *opp_pace_comp_eph_pubkey, const BUF_MEM *auxdata)
191
0
{
192
0
    BUF_MEM *data = NULL, *signature = NULL;
193
194
0
    check(ctx && ctx->ta_ctx, "Invalid arguments");
195
196
    /* Get the data to be signed */
197
0
    data = get_ta_sigdata(my_ta_comp_eph_pubkey, opp_pace_comp_eph_pubkey,
198
0
            ctx->ta_ctx->nonce, auxdata);
199
0
    signature = EAC_sign(ctx->ta_ctx->protocol, ctx->ta_ctx->priv_key, data);
200
201
0
err:
202
0
    if (data)
203
0
        BUF_MEM_free(data);
204
205
0
    return signature;
206
0
}
207
208
int
209
TA_STEP6_verify(const EAC_CTX *ctx, const BUF_MEM *opp_ta_comp_eph_pubkey,
210
           const BUF_MEM *my_pace_comp_eph_pubkey, const BUF_MEM *auxdata,
211
           const BUF_MEM *signature)
212
0
{
213
0
    BUF_MEM *data = NULL;
214
0
    int r = -1;
215
216
0
    check(ctx && ctx->ta_ctx, "Invalid arguments");
217
218
0
    check(ctx->ta_ctx->nonce, "Conditions not satisfied");
219
220
    /* Get the data to be verified */
221
0
    data = get_ta_sigdata(opp_ta_comp_eph_pubkey, my_pace_comp_eph_pubkey,
222
0
            ctx->ta_ctx->nonce, auxdata);
223
0
    r = EAC_verify(ctx->ta_ctx->protocol, ctx->ta_ctx->pub_key, signature, data);
224
225
0
err:
226
0
    if (data)
227
0
        BUF_MEM_free(data);
228
229
0
    return r;
230
0
}