1 /*
2 * sec.c: Cryptography and security (ISO7816-8) functions
3 *
4 * Copyright (C) 2001, 2002 Juha Yrjölä <juha.yrjola@iki.fi>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #if HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <assert.h>
28 #include <ctype.h>
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32
33 #include "internal.h"
34
sc_decipher(sc_card_t * card,const u8 * crgram,size_t crgram_len,u8 * out,size_t outlen)35 int sc_decipher(sc_card_t *card,
36 const u8 * crgram, size_t crgram_len, u8 * out, size_t outlen)
37 {
38 int r;
39
40 if (card == NULL || crgram == NULL || out == NULL) {
41 LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
42 }
43 LOG_FUNC_CALLED(card->ctx);
44 if (card->ops->decipher == NULL)
45 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
46 r = card->ops->decipher(card, crgram, crgram_len, out, outlen);
47 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
48 }
49
sc_compute_signature(sc_card_t * card,const u8 * data,size_t datalen,u8 * out,size_t outlen)50 int sc_compute_signature(sc_card_t *card,
51 const u8 * data, size_t datalen,
52 u8 * out, size_t outlen)
53 {
54 int r;
55
56 if (card == NULL) {
57 return SC_ERROR_INVALID_ARGUMENTS;
58 }
59 LOG_FUNC_CALLED(card->ctx);
60 if (card->ops->compute_signature == NULL)
61 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
62 r = card->ops->compute_signature(card, data, datalen, out, outlen);
63 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
64 }
65
sc_unwrap(sc_card_t * card,const u8 * crgram,size_t crgram_len,u8 * out,size_t outlen)66 int sc_unwrap(sc_card_t *card,
67 const u8 * crgram, size_t crgram_len, u8 * out, size_t outlen)
68 {
69 int r;
70
71 if (card == NULL || crgram == NULL) {
72 return SC_ERROR_INVALID_ARGUMENTS;
73 }
74 LOG_FUNC_CALLED(card->ctx);
75 if (card->ops->unwrap == NULL)
76 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
77 r = card->ops->unwrap(card, crgram, crgram_len);
78 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
79 }
80
sc_wrap(sc_card_t * card,const u8 * crgram,size_t crgram_len,u8 * out,size_t outlen)81 int sc_wrap(sc_card_t *card,
82 const u8 * crgram, size_t crgram_len, u8 * out, size_t outlen)
83 {
84 int r;
85
86 if (card == NULL) {
87 return SC_ERROR_INVALID_ARGUMENTS;
88 }
89 LOG_FUNC_CALLED(card->ctx);
90 if (card->ops->wrap == NULL)
91 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
92 r = card->ops->wrap(card, out, outlen);
93 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
94 }
95
sc_set_security_env(sc_card_t * card,const sc_security_env_t * env,int se_num)96 int sc_set_security_env(sc_card_t *card,
97 const sc_security_env_t *env,
98 int se_num)
99 {
100 int r;
101
102 if (card == NULL) {
103 return SC_ERROR_INVALID_ARGUMENTS;
104 }
105 LOG_FUNC_CALLED(card->ctx);
106 if (card->ops->set_security_env == NULL)
107 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
108 r = card->ops->set_security_env(card, env, se_num);
109 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
110 }
111
sc_restore_security_env(sc_card_t * card,int se_num)112 int sc_restore_security_env(sc_card_t *card, int se_num)
113 {
114 int r;
115
116 if (card == NULL) {
117 return SC_ERROR_INVALID_ARGUMENTS;
118 }
119 LOG_FUNC_CALLED(card->ctx);
120 if (card->ops->restore_security_env == NULL)
121 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
122 r = card->ops->restore_security_env(card, se_num);
123 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
124 }
125
sc_verify(sc_card_t * card,unsigned int type,int ref,const u8 * pin,size_t pinlen,int * tries_left)126 int sc_verify(sc_card_t *card, unsigned int type, int ref,
127 const u8 *pin, size_t pinlen, int *tries_left)
128 {
129 struct sc_pin_cmd_data data;
130
131 memset(&data, 0, sizeof(data));
132 data.cmd = SC_PIN_CMD_VERIFY;
133 data.pin_type = type;
134 data.pin_reference = ref;
135 data.pin1.data = pin;
136 data.pin1.len = pinlen;
137
138 return sc_pin_cmd(card, &data, tries_left);
139 }
140
sc_logout(sc_card_t * card)141 int sc_logout(sc_card_t *card)
142 {
143 if (card->ops->logout == NULL)
144 return SC_ERROR_NOT_SUPPORTED;
145 return card->ops->logout(card);
146 }
147
sc_change_reference_data(sc_card_t * card,unsigned int type,int ref,const u8 * old,size_t oldlen,const u8 * newref,size_t newlen,int * tries_left)148 int sc_change_reference_data(sc_card_t *card, unsigned int type,
149 int ref, const u8 *old, size_t oldlen,
150 const u8 *newref, size_t newlen,
151 int *tries_left)
152 {
153 struct sc_pin_cmd_data data;
154
155 memset(&data, 0, sizeof(data));
156 data.cmd = SC_PIN_CMD_CHANGE;
157 data.pin_type = type;
158 data.pin_reference = ref;
159 data.pin1.data = old;
160 data.pin1.len = oldlen;
161 data.pin2.data = newref;
162 data.pin2.len = newlen;
163
164 return sc_pin_cmd(card, &data, tries_left);
165 }
166
sc_reset_retry_counter(sc_card_t * card,unsigned int type,int ref,const u8 * puk,size_t puklen,const u8 * newref,size_t newlen)167 int sc_reset_retry_counter(sc_card_t *card, unsigned int type, int ref,
168 const u8 *puk, size_t puklen, const u8 *newref,
169 size_t newlen)
170 {
171 struct sc_pin_cmd_data data;
172
173 memset(&data, 0, sizeof(data));
174 data.cmd = SC_PIN_CMD_UNBLOCK;
175 data.pin_type = type;
176 data.pin_reference = ref;
177 data.pin1.data = puk;
178 data.pin1.len = puklen;
179 data.pin2.data = newref;
180 data.pin2.len = newlen;
181
182 return sc_pin_cmd(card, &data, NULL);
183 }
184
185 /*
186 * This is the new style pin command, which takes care of all PIN
187 * operations.
188 * If a PIN was given by the application, the card driver should
189 * send this PIN to the card. If no PIN was given, the driver should
190 * ask the reader to obtain the pin(s) via the pin pad
191 */
sc_pin_cmd(sc_card_t * card,struct sc_pin_cmd_data * data,int * tries_left)192 int sc_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
193 int *tries_left)
194 {
195 int r, debug;
196
197 if (card == NULL) {
198 return SC_ERROR_INVALID_ARGUMENTS;
199 }
200 LOG_FUNC_CALLED(card->ctx);
201
202 debug = card->ctx->debug;
203 if (data->cmd != SC_PIN_CMD_GET_INFO
204 && card->ctx->debug < SC_LOG_DEBUG_PIN) {
205 card->ctx->debug = 0;
206 }
207
208 if (card->ops->pin_cmd) {
209 r = card->ops->pin_cmd(card, data, tries_left);
210 } else if (!(data->flags & SC_PIN_CMD_USE_PINPAD)) {
211 /* Card driver doesn't support new style pin_cmd, fall
212 * back to old interface */
213
214 r = SC_ERROR_NOT_SUPPORTED;
215 switch (data->cmd) {
216 case SC_PIN_CMD_VERIFY:
217 if (card->ops->verify != NULL)
218 r = card->ops->verify(card,
219 data->pin_type,
220 data->pin_reference,
221 data->pin1.data,
222 (size_t) data->pin1.len,
223 tries_left);
224 break;
225 case SC_PIN_CMD_CHANGE:
226 if (card->ops->change_reference_data != NULL)
227 r = card->ops->change_reference_data(card,
228 data->pin_type,
229 data->pin_reference,
230 data->pin1.data,
231 (size_t) data->pin1.len,
232 data->pin2.data,
233 (size_t) data->pin2.len,
234 tries_left);
235 break;
236 case SC_PIN_CMD_UNBLOCK:
237 if (card->ops->reset_retry_counter != NULL)
238 r = card->ops->reset_retry_counter(card,
239 data->pin_type,
240 data->pin_reference,
241 data->pin1.data,
242 (size_t) data->pin1.len,
243 data->pin2.data,
244 (size_t) data->pin2.len);
245 break;
246 }
247 if (r == SC_ERROR_NOT_SUPPORTED)
248 sc_log(card->ctx, "unsupported PIN operation (%d)",
249 data->cmd);
250 } else {
251 sc_log(card->ctx, "Use of pin pad not supported by card driver");
252 r = SC_ERROR_NOT_SUPPORTED;
253 }
254 card->ctx->debug = debug;
255
256 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
257 }
258
259 /*
260 * This function will copy a PIN, convert and pad it as required
261 *
262 * Note about the SC_PIN_ENCODING_GLP encoding:
263 * PIN buffers are always 16 nibbles (8 bytes) and look like this:
264 * 0x2 + len + pin_in_BCD + paddingnibbles
265 * in which the paddingnibble = 0xF
266 * E.g. if PIN = 12345, then sbuf = {0x25, 0x12, 0x34, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF}
267 * E.g. if PIN = 123456789012, then sbuf = {0x2C, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0xFF}
268 * Reference: Global Platform - Card Specification - version 2.0.1' - April 7, 2000
269 */
sc_build_pin(u8 * buf,size_t buflen,struct sc_pin_cmd_pin * pin,int pad)270 int sc_build_pin(u8 *buf, size_t buflen, struct sc_pin_cmd_pin *pin, int pad)
271 {
272 size_t i = 0, j, pin_len = pin->len;
273
274 if (pin->max_length && pin_len > pin->max_length)
275 return SC_ERROR_INVALID_ARGUMENTS;
276
277 if (pin->encoding == SC_PIN_ENCODING_GLP) {
278 while (pin_len > 0 && pin->data[pin_len - 1] == 0xFF)
279 pin_len--;
280 if (pin_len > 12)
281 return SC_ERROR_INVALID_ARGUMENTS;
282 for (i = 0; i < pin_len; i++) {
283 if (pin->data[i] < '0' || pin->data[i] > '9')
284 return SC_ERROR_INVALID_ARGUMENTS;
285 }
286 buf[0] = 0x20 | (u8) pin_len;
287 buf++;
288 buflen--;
289 }
290
291 /* PIN given by application, encode if required */
292 if (pin->encoding == SC_PIN_ENCODING_ASCII) {
293 if (pin_len > buflen)
294 return SC_ERROR_BUFFER_TOO_SMALL;
295 memcpy(buf, pin->data, pin_len);
296 i = pin_len;
297 } else if (pin->encoding == SC_PIN_ENCODING_BCD || pin->encoding == SC_PIN_ENCODING_GLP) {
298 if (pin_len > 2 * buflen)
299 return SC_ERROR_BUFFER_TOO_SMALL;
300 for (i = j = 0; j < pin_len; j++) {
301 if (!isdigit(pin->data[j])) {
302 return SC_ERROR_INVALID_DATA;
303 }
304 buf[i] <<= 4;
305 buf[i] |= pin->data[j] & 0xf;
306 if (j & 1)
307 i++;
308 }
309 if (j & 1) {
310 buf[i] <<= 4;
311 buf[i] |= pin->pad_char & 0xf;
312 i++;
313 }
314 }
315
316 /* Pad to maximum PIN length if requested */
317 if (pad || pin->encoding == SC_PIN_ENCODING_GLP) {
318 size_t pad_length = pin->pad_length;
319 u8 pad_char = pin->encoding == SC_PIN_ENCODING_GLP ? 0xFF : pin->pad_char;
320
321 if (pin->encoding == SC_PIN_ENCODING_BCD)
322 pad_length >>= 1;
323 if (pin->encoding == SC_PIN_ENCODING_GLP)
324 pad_length = 8;
325
326 if (pad_length > buflen)
327 return SC_ERROR_BUFFER_TOO_SMALL;
328
329 if (pad_length && i < pad_length) {
330 memset(buf + i, pad_char, pad_length - i);
331 i = pad_length;
332 }
333 }
334
335 return i;
336 }
337