00001
00037 #include <avr/sleep.h>
00038 #include <util/delay.h>
00039 #include <avr/wdt.h>
00040 #include <avr/eeprom.h>
00041 #include <string.h>
00042 #include <stdlib.h>
00043
00044 #include "apps.h"
00045 #include "emv.h"
00046 #include "terminal.h"
00047 #include "scd_hal.h"
00048 #include "serial.h"
00049 #include "scd_io.h"
00050 #include "scd_values.h"
00051 #include "VirtualSerial.h"
00052
00053
00055 #define EEPROM_SIZE 4096
00056
00058 static const char strAT_CRST[] = "AT+CRST";
00059 static const char strAT_CTERM[] = "AT+CTERM";
00060 static const char strAT_CLET[] = "AT+CLET";
00061 static const char strAT_CGEE[] = "AT+CGEE";
00062 static const char strAT_CEEE[] = "AT+CEEE";
00063 static const char strAT_CGBM[] = "AT+CGBM";
00064 static const char strAT_CCINIT[] = "AT+CCINIT";
00065 static const char strAT_CCAPDU[] = "AT+CCAPDU";
00066 static const char strAT_CCEND[] = "AT+CCEND";
00067 static const char strAT_RBAD[] = "AT BAD\r\n";
00068 static const char strAT_ROK[] = "AT OK\r\n";
00069
00070
00087 char* ProcessSerialData(const char* data, log_struct_t *logger)
00088 {
00089 uint8_t tmp;
00090 char *atparams = NULL;
00091 AT_CMD atcmd;
00092
00093
00094
00095
00096 tmp = ParseATCommand(data, &atcmd, &atparams);
00097 if(tmp != 0)
00098 return strdup(strAT_RBAD);
00099
00100 if(atcmd == AT_CRST)
00101 {
00102
00103 wdt_enable(WDTO_1S);
00104 while(1);
00105 }
00106 else if(atcmd == AT_CTERM)
00107 {
00108 Terminal(logger);
00109 }
00110 else if(atcmd == AT_CLET)
00111 {
00112 ForwardData(logger);
00113 }
00114 else if(atcmd == AT_CGEE)
00115 {
00116
00117 SendEEPROMHexVSerial();
00118 }
00119 else if(atcmd == AT_CEEE)
00120 {
00121 ResetEEPROM();
00122 }
00123 else if(atcmd == AT_CGBM)
00124 {
00125 RunBootloader();
00126 }
00127 else if(atcmd == AT_CCINIT)
00128 {
00129 TerminalVSerial(logger);
00130 }
00131 else
00132 {
00133 return strdup(strAT_RBAD);
00134 }
00135
00136 return strdup(strAT_ROK);
00137 }
00138
00151 uint8_t ParseATCommand(const char *data, AT_CMD *atcmd, char **atparams)
00152 {
00153 uint8_t len, pos;
00154
00155 *atparams = NULL;
00156 *atcmd = AT_NONE;
00157
00158 if(data == NULL || data[0] != 'A' || data[1] != 'T')
00159 return RET_ERR_PARAM;
00160
00161 len = strlen(data);
00162 if(len < 3)
00163 return RET_ERR_PARAM;
00164
00165 if(data[2] == '+')
00166 {
00167 if(strstr(data, strAT_CRST) == data)
00168 {
00169 *atcmd = AT_CRST;
00170 return 0;
00171 }
00172 else if(strstr(data, strAT_CTERM) == data)
00173 {
00174 *atcmd = AT_CTERM;
00175 return 0;
00176 }
00177 else if(strstr(data, strAT_CLET) == data)
00178 {
00179 *atcmd = AT_CLET;
00180 return 0;
00181 }
00182 else if(strstr(data, strAT_CGEE) == data)
00183 {
00184 *atcmd = AT_CGEE;
00185 return 0;
00186 }
00187 else if(strstr(data, strAT_CEEE) == data)
00188 {
00189 *atcmd = AT_CEEE;
00190 return 0;
00191 }
00192 else if(strstr(data, strAT_CGBM) == data)
00193 {
00194 *atcmd = AT_CGBM;
00195 return 0;
00196 }
00197 else if(strstr(data, strAT_CCINIT) == data)
00198 {
00199 *atcmd = AT_CCINIT;
00200 return 0;
00201 }
00202 else if(strstr(data, strAT_CCAPDU) == data)
00203 {
00204 *atcmd = AT_CCAPDU;
00205 pos = strlen(strAT_CCAPDU);
00206 if((strlen(data) > pos + 1) && data[pos] == '=')
00207 *atparams = &data[pos + 1];
00208 return 0;
00209 }
00210 else if(strstr(data, strAT_CCEND) == data)
00211 {
00212 *atcmd = AT_CCEND;
00213 return 0;
00214 }
00215 }
00216
00217 return 0;
00218 }
00219
00220
00228 uint8_t SendEEPROMHexVSerial()
00229 {
00230 uint8_t eedata[32];
00231 uint16_t eeaddr;
00232 char eestr[78];
00233 uint8_t eesum;
00234 uint8_t i, k, t;
00235
00236 eeaddr = 0;
00237 memset(eestr, 0, 78);
00238 eestr[0] = ':';
00239 eestr[1] = '2';
00240 eestr[2] = '0';
00241 eestr[7] = '0';
00242 eestr[8] = '0';
00243 eestr[75] = '\r';
00244 eestr[76] = '\n';
00245
00246 for(k = 0; k < EEPROM_SIZE / 32; k++)
00247 {
00248 eeprom_read_block(eedata, (void*)eeaddr, 32);
00249 eesum = 32 + ((eeaddr >> 8) & 0xFF) + (eeaddr & 0xFF);
00250 t = (eeaddr >> 12) & 0x0F;
00251 eestr[3] = (t < 0x0A) ? (t + '0') : (t + '7');
00252 t = (eeaddr >> 8) & 0x0F;
00253 eestr[4] = (t < 0x0A) ? (t + '0') : (t + '7');
00254 t = (eeaddr >> 4) & 0x0F;
00255 eestr[5] = (t < 0x0A) ? (t + '0') : (t + '7');
00256 t = eeaddr & 0x0F;
00257 eestr[6] = (t < 0x0A) ? (t + '0') : (t + '7');
00258
00259 for(i = 0; i < 32; i++)
00260 {
00261 eesum = eesum + eedata[i];
00262 t = (eedata[i] >> 4) & 0x0F;
00263 eestr[9 + i * 2] = (t < 0x0A) ? (t + '0') : (t + '7');
00264 t = eedata[i] & 0x0F;
00265 eestr[10 + i * 2] = (t < 0x0A) ? (t + '0') : (t + '7');
00266 }
00267
00268 eesum = (uint8_t)((eesum ^ 0xFF) + 1);
00269 t = (eesum >> 4) & 0x0F;
00270 eestr[73] = (t < 0x0A) ? (t + '0') : (t + '7');
00271 t = eesum & 0x0F;
00272 eestr[74] = (t < 0x0A) ? (t + '0') : (t + '7');
00273
00274 if(SendHostData(eestr))
00275 return RET_ERROR;
00276
00277 eeaddr = eeaddr + 32;
00278 }
00279
00280 memset(eestr, 0, 78);
00281 eestr[0] = ':';
00282 eestr[1] = '0';
00283 eestr[2] = '0';
00284 eestr[3] = '0';
00285 eestr[4] = '0';
00286 eestr[5] = '0';
00287 eestr[6] = '0';
00288 eestr[7] = '0';
00289 eestr[8] = '1';
00290 eestr[9] = 'F';
00291 eestr[10] = 'F';
00292 eestr[11] = '\r';
00293 eestr[12] = '\n';
00294 if(SendHostData(eestr))
00295 return RET_ERROR;
00296
00297 return 0;
00298 }
00299
00300
00312 void TerminalVSerial(log_struct_t *logger)
00313 {
00314 uint8_t convention, proto, TC1, TA3, TB3;
00315 uint8_t tmp, i, lparams, ldata, result;
00316 char *buf, *atparams = NULL;
00317 char reply[512];
00318 uint8_t data[256];
00319 AT_CMD atcmd;
00320 RAPDU *response = NULL;
00321 CAPDU *command = NULL;
00322
00323
00324
00325 if(!IsICCInserted())
00326 {
00327 fprintf(stderr, "ICC not inserted\n");
00328 _delay_ms(500);
00329 SendHostData(strAT_RBAD);
00330 wdt_enable(WDTO_60MS);
00331 while(1);
00332 }
00333
00334 result = ResetICC(0, &convention, &proto, &TC1, &TA3, &TB3, logger);
00335 if(result)
00336 {
00337 fprintf(stderr, "ICC reset failed\n");
00338 _delay_ms(500);
00339 fprintf(stderr, "result: %2X\n", result);
00340 _delay_ms(500);
00341 SendHostData(strAT_RBAD);
00342 wdt_enable(WDTO_60MS);
00343 while(1);
00344 }
00345 if(proto != 0)
00346 {
00347 fprintf(stderr, "bad ICC proto\n");
00348 _delay_ms(500);
00349 SendHostData(strAT_RBAD);
00350 wdt_enable(WDTO_60MS);
00351 while(1);
00352 }
00353
00354
00355 SendHostData(strAT_ROK);
00356
00357
00358
00359 while(1)
00360 {
00361 buf = GetHostData(255);
00362 if(buf == NULL)
00363 {
00364 _delay_ms(100);
00365 continue;
00366 }
00367
00368 tmp = ParseATCommand(buf, &atcmd, &atparams);
00369 lparams = strlen(atparams);
00370
00371 if(atcmd == AT_CCEND)
00372 {
00373 SendHostData(strAT_ROK);
00374 wdt_enable(WDTO_60MS);
00375 while(1);
00376 }
00377 else if(atcmd != AT_CCAPDU || atparams == NULL || lparams < 10 || (lparams % 2) != 0)
00378 {
00379 SendHostData(strAT_RBAD);
00380 free(buf);
00381 continue;
00382 }
00383
00384 memset(data, 0, 256);
00385 for(i = 0; i < lparams/2; i++)
00386 {
00387 data[i] = hexCharsToByte(atparams[2*i], atparams[2*i + 1]);
00388 }
00389 free(buf);
00390
00391 ldata = (lparams - 10) / 2;
00392 command = MakeCommand(
00393 data[0], data[1], data[2], data[3], data[4],
00394 &data[5], ldata);
00395 if(command == NULL)
00396 {
00397 SendHostData(strAT_RBAD);
00398 continue;
00399 }
00400
00401
00402 response = TerminalSendT0Command(command, convention, TC1, logger);
00403 FreeCAPDU(command);
00404 if(response == NULL)
00405 {
00406 FreeCAPDU(command);
00407 SendHostData(strAT_RBAD);
00408 continue;
00409 }
00410
00411 memset(reply, 0, 512);
00412 reply[0] = nibbleToHexChar(response->repStatus->sw1, 1);
00413 reply[1] = nibbleToHexChar(response->repStatus->sw1, 0);
00414 reply[2] = nibbleToHexChar(response->repStatus->sw2, 1);
00415 reply[3] = nibbleToHexChar(response->repStatus->sw2, 0);
00416 for(i = 0; i < response->lenData; i++)
00417 {
00418 reply[4 + i*2] = nibbleToHexChar(response->repData[i], 1);
00419 reply[5 + i*2] = nibbleToHexChar(response->repData[i], 0);
00420 }
00421 reply[4 + i] = '\r';
00422 reply[5 + i] = '\n';
00423 FreeRAPDU(response);
00424 SendHostData(reply);
00425 }
00426 }
00427
00428
00437 uint8_t hexCharsToByte(char c1, char c2)
00438 {
00439 uint8_t result = 0;
00440
00441 if(c1 >= '0' && c1 <= '9')
00442 result = c1 - '0';
00443 else if(c1 >= 'A' && c1 <= 'F')
00444 result = c1 - '7';
00445 else if(c1 >= 'a' && c1 <= 'f')
00446 result = c1 - 'W';
00447 else
00448 return 0;
00449
00450 result = result << 4;
00451
00452 if(c2 >= '0' && c2 <= '9')
00453 result |= c2 - '0';
00454 else if(c2 >= 'A' && c2 <= 'F')
00455 result |= c2 - '7';
00456 else if(c2 >= 'a' && c2 <= 'f')
00457 result |= c2 - 'W';
00458 else
00459 return 0;
00460
00461 return result;
00462 }
00463
00472 char nibbleToHexChar(uint8_t b, uint8_t high)
00473 {
00474 char result = '0';
00475
00476 if(high)
00477 b = (b & 0xF0) >> 4;
00478 else
00479 b = b & 0x0F;
00480
00481 if(b < 10)
00482 result = b + '0';
00483 else if(b < 16)
00484 result = b + '7';
00485
00486 return result;
00487 }
00488