1 /*****************************************************************************
2 * Copyright ©2017-2019 Gemalto – a Thales Company. All rights Reserved.
3 *
4 * This copy is licensed under the Apache License, Version 2.0 (the "License");
5 * You may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0 or https://www.apache.org/licenses/LICENSE-2.0.html
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 * See the License for the specific language governing permissions and limitations under the License.
11
12 ****************************************************************************/
13
14 /**
15 * @file
16 * $Author$
17 * $Revision$
18 * $Date$
19 *
20 * libse-gto main functions.
21 *
22 */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <stddef.h>
27 #include <stdarg.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <stdint.h>
33 #include <fcntl.h>
34 #include <log/log.h>
35
36 #include "se-gto/libse-gto.h"
37 #include "libse-gto-private.h"
38 #include "spi.h"
39
40 #define SE_GTO_GTODEV "/dev/gto"
41
42 SE_GTO_EXPORT void *
se_gto_get_userdata(struct se_gto_ctx * ctx)43 se_gto_get_userdata(struct se_gto_ctx *ctx)
44 {
45 if (ctx == NULL)
46 return NULL;
47
48 return ctx->userdata;
49 }
50
51 SE_GTO_EXPORT void
se_gto_set_userdata(struct se_gto_ctx * ctx,void * userdata)52 se_gto_set_userdata(struct se_gto_ctx *ctx, void *userdata)
53 {
54 if (ctx == NULL)
55 return;
56
57 ctx->userdata = userdata;
58 }
59
60 static int
log_level(const char * priority)61 log_level(const char *priority)
62 {
63 char *endptr;
64 int prio;
65
66 prio = strtol(priority, &endptr, 10);
67 if ((endptr[0] == '\0') || isspace(endptr[0]))
68 return prio;
69
70 if (strncmp(priority, "err", 3) == 0)
71 return 0;
72
73 if (strncmp(priority, "info", 4) == 0)
74 return 3;
75
76 if (strncmp(priority, "debug", 5) == 0)
77 return 4;
78
79 return 0;
80 }
81
82 static void
log_stderr(struct se_gto_ctx * ctx,const char * s)83 log_stderr(struct se_gto_ctx *ctx, const char *s)
84 {
85 //fputs(s, stderr);
86 ALOGD("%s",s);
87 }
88
89 SE_GTO_EXPORT int
se_gto_new(struct se_gto_ctx ** c)90 se_gto_new(struct se_gto_ctx **c)
91 {
92 const char *env;
93 struct se_gto_ctx *ctx;
94
95 ctx = calloc(1, sizeof(struct se_gto_ctx));
96 if (!ctx) {
97 errno = ENOMEM;
98 return -1;
99 }
100
101 isot1_init(&ctx->t1);
102
103 ctx->log_fn = log_stderr;
104
105 ctx->gtodev = SE_GTO_GTODEV;
106
107 ctx->log_level = 2;
108 /* environment overwrites config */
109 env = getenv("SE_GTO_LOG");
110 if (env != NULL)
111 se_gto_set_log_level(ctx, log_level(env));
112
113 dbg("ctx %p created\n", ctx);
114 dbg("log_level=%d\n", ctx->log_level);
115 *c = ctx;
116 return 0;
117 }
118
119 SE_GTO_EXPORT int
se_gto_get_log_level(struct se_gto_ctx * ctx)120 se_gto_get_log_level(struct se_gto_ctx *ctx)
121 {
122 return ctx->log_level;
123 }
124
125 SE_GTO_EXPORT void
se_gto_set_log_level(struct se_gto_ctx * ctx,int level)126 se_gto_set_log_level(struct se_gto_ctx *ctx, int level)
127 {
128 if (level < 0)
129 level = 0;
130 else if (level > 4)
131 level = 4;
132 ctx->log_level = level;
133 }
134
135 SE_GTO_EXPORT se_gto_log_fn *
se_gto_get_log_fn(struct se_gto_ctx * ctx)136 se_gto_get_log_fn(struct se_gto_ctx *ctx)
137 {
138 return ctx->log_fn;
139 }
140
141 SE_GTO_EXPORT void
se_gto_set_log_fn(struct se_gto_ctx * ctx,se_gto_log_fn * fn)142 se_gto_set_log_fn(struct se_gto_ctx *ctx, se_gto_log_fn *fn)
143 {
144 ctx->log_fn = fn;
145 }
146
147 SE_GTO_EXPORT const char *
se_gto_get_gtodev(struct se_gto_ctx * ctx)148 se_gto_get_gtodev(struct se_gto_ctx *ctx)
149 {
150 return ctx->gtodev;
151 }
152
153 SE_GTO_EXPORT void
se_gto_set_gtodev(struct se_gto_ctx * ctx,const char * gtodev)154 se_gto_set_gtodev(struct se_gto_ctx *ctx, const char *gtodev)
155 {
156 ctx->gtodev = strdup(gtodev);
157 }
158
159 SE_GTO_EXPORT int
se_gto_reset(struct se_gto_ctx * ctx,void * atr,size_t r)160 se_gto_reset(struct se_gto_ctx *ctx, void *atr, size_t r)
161 {
162 int err;
163
164 err = isot1_reset(&ctx->t1);
165 if (err < 0) {
166 errno = -err;
167 ctx->check_alive = 1;
168 }
169 else {
170 err = isot1_get_atr(&ctx->t1, atr, r);
171 if (err < 0)
172 errno = -err;
173 }
174 return err;
175 }
176
177 SE_GTO_EXPORT int
se_gto_apdu_transmit(struct se_gto_ctx * ctx,const void * apdu,int n,void * resp,int r)178 se_gto_apdu_transmit(struct se_gto_ctx *ctx, const void *apdu, int n, void *resp, int r)
179 {
180 if (!apdu || (n < 4) || !resp || (r < 2)) {
181 errno = EINVAL;
182 return -1;
183 }
184 r = isot1_transceive(&ctx->t1, apdu, n, resp, r);
185 dbg("isot1_transceive: r=%d\n", r);
186 dbg("isot1_transceive: ctx->t1.recv.end - ctx->t1.recv.start = %d\n", ctx->t1.recv.end - ctx->t1.recv.start);
187 dbg("isot1_transceive: ctx->t1.recv.size = %zu\n", ctx->t1.recv.size);
188 dbg("isot1_transceive: ctx->t1.buf[2] = %02X\n", ctx->t1.buf[2]);
189 if (r < 0) {
190 errno = -r;
191 err("failed to read APDU response, %s\n", strerror(-r));
192 } else if (r < 2) {
193 err("APDU response too short, only %d bytes, needs 2 at least\n", r);
194 }
195 if (r < 2){
196 ctx->check_alive = 1;
197 return -1;
198 } else
199 return r;
200 }
201
202 SE_GTO_EXPORT int
se_gto_open(struct se_gto_ctx * ctx)203 se_gto_open(struct se_gto_ctx *ctx)
204 {
205 info("eSE GTO: using %s\n", ctx->gtodev);
206
207 if (spi_setup(ctx) < 0) {
208 err("failed to set up se-gto.\n");
209 return -1;
210 }
211
212 ctx->check_alive = 0;
213
214 isot1_bind(&ctx->t1, 0x2, 0x1);
215
216 dbg("fd: spi=%d\n", ctx->t1.spi_fd);
217 return 0;
218 }
219
220 int gtoSPI_checkAlive(struct se_gto_ctx *ctx);
gtoSPI_checkAlive(struct se_gto_ctx * ctx)221 int gtoSPI_checkAlive(struct se_gto_ctx *ctx)
222 {
223 int ret = 0;
224 unsigned char apdu[5]= {0x80,0xCA,0x9F,0x7F,0x2D};
225 unsigned char resp[258] = {0,};
226
227 /*Check Alive implem*/
228 ret = se_gto_apdu_transmit(ctx, apdu, 5, resp, sizeof(resp));
229 if(ret < 0){
230 return -1;
231 }
232
233 return 0;
234 }
235
236 SE_GTO_EXPORT int
se_gto_close(struct se_gto_ctx * ctx)237 se_gto_close(struct se_gto_ctx *ctx)
238 {
239 int status = 0;
240
241 if(ctx) dbg("se_gto_close check_alive = %d\n", ctx->check_alive);
242 if (ctx->check_alive == 1)
243 if (gtoSPI_checkAlive(ctx) != 0) status = 0xDEAD;
244
245 (void)isot1_release(&ctx->t1);
246 (void)spi_teardown(ctx);
247 log_teardown(ctx);
248 if(ctx) free(ctx);
249 return status;
250 }
251