Coverage Report

Created: 2025-08-26 06:43

/src/opensc/src/libopensc/pkcs15-cardos.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * PKCS15 emulation layer for CardOS cards
3
 * Adapted from PKCS15 emulation layer for IAS/ECC card.
4
 *
5
 * Copyright (C) 2020, Douglas E. Engert <DEEngert@gmail.com>
6
 * Copyright (C) 2016, Viktor Tarasov <viktor.tarasov@gmail.com>
7
 * Copyright (C) 2004, Bud P. Bruegger <bud@comune.grosseto.it>
8
 * Copyright (C) 2004, Antonino Iacono <ant_iacono@tin.it>
9
 * Copyright (C) 2003, Olaf Kirch <okir@suse.de>
10
 *
11
 * This library is free software; you can redistribute it and/or
12
 * modify it under the terms of the GNU Lesser General Public
13
 * License as published by the Free Software Foundation; either
14
 * version 2.1 of the License, or (at your option) any later version.
15
 *
16
 * This library is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19
 * Lesser General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Lesser General Public
22
 * License along with this library; if not, write to the Free Software
23
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24
 */
25
26
#ifdef HAVE_CONFIG_H
27
#include "config.h"
28
#endif
29
30
#include <stdlib.h>
31
#include <string.h>
32
#include <stdio.h>
33
34
#include "internal.h"
35
#include "pkcs15.h"
36
37
38
/*
39
 * Called after sc_pkcs15_bind_internal
40
 * Create new flags based on supported_algos.
41
 */
42
static int cardos_fix_token_info(sc_pkcs15_card_t *p15card)
43
67
{
44
67
  sc_card_t *card;
45
67
  struct sc_supported_algo_info (*saa)[SC_MAX_SUPPORTED_ALGORITHMS];
46
67
  struct sc_supported_algo_info *sa;
47
67
  struct sc_cardctl_cardos_pass_algo_flags *passed = NULL;
48
67
  int r = 0;
49
67
  int i;
50
51
67
  card = p15card->card;
52
53
67
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
54
55
67
  passed = calloc(1, sizeof(struct sc_cardctl_cardos_pass_algo_flags));
56
67
  if (!passed)
57
67
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_ENOUGH_MEMORY);
58
59
67
  passed->pass = 1; /* get used_flags and card_flags from card */
60
67
  r = sc_card_ctl(p15card->card, SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS, passed);
61
67
  if (r < 0) {
62
0
    free(passed);
63
0
    LOG_FUNC_RETURN(card->ctx, r);
64
0
  }
65
66
67
  saa = &(p15card->tokeninfo->supported_algos);
67
68
67
  sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Original Flags: 0x%8.8lx card->flags:0x%8.8lx", passed->used_flags, passed->card_flags);
69
70
67
  if (passed->card_flags) { /* user forced the flags, use them */
71
0
    passed->new_flags = passed->card_flags; /* from card_atr flags */
72
67
  } else {
73
74
150
    for (i = 0, sa = saa[0]; i < SC_MAX_SUPPORTED_ALGORITHMS; i++, sa++) {
75
76
150
      if (sa->reference == 0 && sa->mechanism == 0
77
150
          && sa->operations == 0 && sa->algo_ref == 0)
78
67
        break;
79
80
83
      sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "supported_algos[%d] mechanism:0x%8.8x", i, sa->mechanism);
81
83
      switch(sa->mechanism) {
82
26
      case 0x01 :
83
        /*
84
         * Card appears to use lower 4 bits of reference as key, and upper
85
         * 4 bits as mech for card.
86
         * Also has a bug if mechanism = 1 (CKM_RSA_PKCS1) and reference 0x10 
87
         * bit is set mechanism should be 3 (CKM_RSA_X_509) 
88
         * correct the mechanism in tokenInfo
89
         */
90
26
        if (sa->reference & 0x10) {
91
16
          sc_log(card->ctx, "Changing mechanism to CKM_RSA_X_509 based on reference");
92
16
          passed->new_flags |= SC_ALGORITHM_RSA_RAW
93
16
            | SC_ALGORITHM_RSA_PAD_NONE;
94
16
          sa->mechanism = 0x03;
95
16
        } else
96
10
        passed->new_flags |= SC_ALGORITHM_RSA_PAD_PKCS1;
97
26
        break;
98
10
      case 0x03 :
99
10
        passed->new_flags |= SC_ALGORITHM_RSA_RAW
100
10
          | SC_ALGORITHM_RSA_PAD_NONE;
101
10
        break;
102
10
      case 0x06 :
103
10
        passed->new_flags |= SC_ALGORITHM_RSA_HASH_SHA1;
104
10
        break;
105
0
      case 0x1041:
106
0
        passed->ec_flags |= SC_ALGORITHM_ECDSA_RAW;
107
        /* no old_ec_flags */
108
        /* TODO turn on sizes from  ec curves OIDS */
109
0
        break;
110
37
      default:
111
37
        sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "UNKNOWN MECH: 0x%8.8x", sa->mechanism);
112
83
      }
113
114
83
      sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "New_flags 0x%8.8lx New_ec_flags: 0x%8.8lx",
115
83
        passed->new_flags, passed->ec_flags);
116
83
    }
117
118
67
    if (passed->new_flags == 0) {
119
51
      if (p15card->tokeninfo && p15card->tokeninfo->flags & SC_PKCS15_TOKEN_EID_COMPLIANT) {
120
18
        sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "EID_COMPLIANT flag found");
121
18
        passed->new_flags = (passed->used_flags & ~SC_ALGORITHM_SPECIFIC_FLAGS) | SC_ALGORITHM_RSA_PAD_PKCS1;
122
18
      } else
123
33
        passed->new_flags = passed->used_flags; /* from default cardos_init */
124
51
    }
125
67
  }
126
127
67
  sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"Final New_flags 0x%8.8lx New_ec_flags: 0x%8.8lx", passed->new_flags, passed->ec_flags);
128
129
67
  passed->pass = 2; /* tell card driver to use the new flags */
130
67
  r = sc_card_ctl(p15card->card, SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS, passed);
131
132
67
  free(passed);
133
67
  LOG_FUNC_RETURN(card->ctx, r);
134
67
}
135
136
static int
137
cardos_pkcs15emu_detect_card(sc_pkcs15_card_t *p15card)
138
7.60k
{
139
7.60k
  if (p15card->card->type <  SC_CARD_TYPE_CARDOS_BASE)
140
191
    return SC_ERROR_WRONG_CARD;
141
142
7.40k
  if (p15card->card->type >= SC_CARD_TYPE_CARDOS_BASE + 1000)
143
6.92k
    return SC_ERROR_WRONG_CARD;
144
145
484
  return SC_SUCCESS;
146
7.40k
}
147
148
149
static int
150
sc_pkcs15emu_cardos_init(struct sc_pkcs15_card *p15card, struct sc_aid *aid)
151
484
{
152
484
  sc_card_t *card = p15card->card;
153
484
  int r;
154
155
484
  LOG_FUNC_CALLED(card->ctx);
156
157
484
  r = sc_pkcs15_bind_internal(p15card, aid);
158
484
  LOG_TEST_RET(card->ctx, r, "sc_pkcs15_bind_internal failed");
159
160
  /* If card has created algorithms, return  */
161
84
  sc_log(card->ctx, " card->algorithms:%p card->algorithm_count:%d", card->algorithms, card->algorithm_count);
162
84
  if (!card->algorithms && card->algorithm_count == 0) {
163
67
    r = cardos_fix_token_info(p15card);
164
67
  }
165
166
84
  LOG_FUNC_RETURN(card->ctx, r);
167
84
}
168
169
170
int
171
sc_pkcs15emu_cardos_init_ex(struct sc_pkcs15_card *p15card, struct sc_aid *aid)
172
7.60k
{
173
7.60k
  if (cardos_pkcs15emu_detect_card(p15card))
174
7.11k
    return SC_ERROR_WRONG_CARD;
175
176
484
  return sc_pkcs15emu_cardos_init(p15card, aid);
177
7.60k
}