fareqr.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. /*
  2. * Copyright (c) 2021 Clementine Computing LLC.
  3. *
  4. * This file is part of PopuFare.
  5. *
  6. * PopuFare is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * PopuFare 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
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with PopuFare. If not, see <https://www.gnu.org/licenses/>.
  18. *
  19. */
  20. #include "fareqr.h"
  21. // AES CBC, sha256 message digest, with salt.
  22. // Functions modified from https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption
  23. //
  24. // openssl example commands to encrypt/decrypt:
  25. // msg=";123456789012345?"
  26. // key="oovevobie8woid1Ou3iu6aboochei2AeKoceeCh1iePheuRae4Yai1dahtheegi7"
  27. // openssl enc -aes-256-cbc -in <( echo -n "$msg" ) -out /dev/stdout -pass pass:"$key" -e -base64 -md sha256
  28. //
  29. // ---
  30. //
  31. // to descypt with openssl
  32. //
  33. // openssl aes-256-cbc -d -a -in <( echo "U2FsdGVkX19gpKzk+Y5SGgnQr1uwpUYUpea6nu77wJfG6bD4GZpRneSaxaallz0n" ) -out /dev/stdout -pass pass:"$key" -md sha256
  34. //
  35. static int aes_encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext) {
  36. EVP_CIPHER_CTX *ctx;
  37. int len;
  38. int ciphertext_len;
  39. // Create and initialise the context
  40. if(!(ctx = EVP_CIPHER_CTX_new())) { return -1; }
  41. // Initialise the encryption operation. IMPORTANT - ensure you use a key
  42. // and IV size appropriate for your cipher
  43. // In this example we are using 256 bit AES (i.e. a 256 bit key). The
  44. // IV size for *most* modes is the same as the block size. For AES this
  45. // is 128 bits
  46. //
  47. if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) { return -2; }
  48. // Provide the message to be encrypted, and obtain the encrypted output.
  49. // EVP_EncryptUpdate can be called multiple times if necessary
  50. //
  51. if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) { return -3; }
  52. ciphertext_len = len;
  53. // Finalise the encryption. Further ciphertext bytes may be written at
  54. // this stage.
  55. //
  56. if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) { return -4; }
  57. ciphertext_len += len;
  58. // Clean up
  59. //
  60. EVP_CIPHER_CTX_free(ctx);
  61. return ciphertext_len;
  62. }
  63. static int aes_decrypt(unsigned char *ciphertext, int ciphertext_len, unsigned char *key, unsigned char *iv, unsigned char *plaintext) {
  64. EVP_CIPHER_CTX *ctx;
  65. int plaintext_len, len;
  66. // Create and initialise the context
  67. //
  68. if(!(ctx = EVP_CIPHER_CTX_new())) { return -1; }
  69. // Initialise the decryption operation. IMPORTANT - ensure you use a key
  70. // and IV size appropriate for your cipher
  71. // In this example we are using 256 bit AES (i.e. a 256 bit key). The
  72. // IV size for *most* modes is the same as the block size. For AES this
  73. // is 128 bits
  74. //
  75. if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv)) { return -2; }
  76. // Provide the message to be decrypted, and obtain the plaintext output.
  77. // EVP_DecryptUpdate can be called multiple times if necessary.
  78. //
  79. if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) { return -3; }
  80. plaintext_len = len;
  81. // Finalise the decryption. Further plaintext bytes may be written at
  82. // this stage.
  83. //
  84. if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len)) { return -4; }
  85. plaintext_len += len;
  86. // Clean up
  87. //
  88. EVP_CIPHER_CTX_free(ctx);
  89. return plaintext_len;
  90. }
  91. // Helper function to take secret key/pass (pass_key) and the encoded
  92. // base64 string and decrypt it with AES CBC 256, sha256 message digest.
  93. //
  94. // return the number of bytes decoded on success
  95. // return non-positive number on error
  96. //
  97. static int decode_b64(unsigned char *decrypt_text,
  98. unsigned char *pass_key,
  99. unsigned char *enc_b64) {
  100. int i=0, _ret = 0, r=0;
  101. unsigned char *enc_b = NULL, salt[8];
  102. unsigned char *key = NULL, *iv = NULL, *ciphertext_b = NULL;
  103. size_t enc_len=0, enc_size=0, ciphertext_len;
  104. if ((!decrypt_text) || (!pass_key) || (!enc_b64)) { return -9; }
  105. enc_size = Base64decode_len((char *)enc_b64);
  106. if (enc_size < 1) {
  107. _ret=-1;
  108. goto _decode_b64_cleanup;
  109. }
  110. enc_b = (unsigned char *)calloc(enc_size, sizeof(char));
  111. if (!enc_b) {
  112. _ret=-2;
  113. goto _decode_b64_cleanup;
  114. }
  115. Base64decode((char *)enc_b, (char *)enc_b64);
  116. enc_len = enc_size-1;
  117. // Check exmpanded string is well formed (has "Salted__" prefix, etc.)
  118. // and extract the salt
  119. //
  120. if (enc_len < 16) {
  121. _ret = -3;
  122. goto _decode_b64_cleanup;
  123. }
  124. if (strncmp((char *)enc_b, "Salted__", 8)!=0) {
  125. _ret = -4;
  126. goto _decode_b64_cleanup;
  127. }
  128. for (i=0; i<8; i++) { salt[i] = enc_b[i+8]; }
  129. // Move past the salt prefix 8 bytes) and 8 bytes of salt
  130. //
  131. ciphertext_b = enc_b + 16;
  132. ciphertext_len = enc_len - 16;
  133. // Allocate iv, key and extract them from the salt and pass phrase
  134. //
  135. iv = (unsigned char *)calloc(256, sizeof(char));
  136. key = (unsigned char *)calloc(256, sizeof(char));
  137. r = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha256(), salt, pass_key, strlen((const char *)pass_key), 1, key, iv);
  138. if (!r) {
  139. _ret = -5;
  140. goto _decode_b64_cleanup;
  141. }
  142. r = aes_decrypt(ciphertext_b, ciphertext_len, key, iv, decrypt_text);
  143. if (r<=0) {
  144. _ret = -6;
  145. goto _decode_b64_cleanup;
  146. }
  147. decrypt_text[r] = '\0';
  148. _ret = r;
  149. _decode_b64_cleanup:
  150. if (enc_b) { free(enc_b); }
  151. if (key) { free(key); }
  152. if (iv) { free(iv); }
  153. return _ret;
  154. }
  155. static int encode_b64(unsigned char *enc_b64,
  156. unsigned char *pass_key,
  157. unsigned char *msg) {
  158. int i=0, _ret = 0, r=0;
  159. unsigned char *enc_b = NULL;
  160. unsigned char *key = NULL, *iv = NULL;
  161. size_t b64_sz=0, enc_len=0;
  162. unsigned char salt[8];
  163. char _pfx[] = "Salted__";
  164. if ((!enc_b64) || (!pass_key) || (!msg)) { return -9; }
  165. for (i=0; i<8; i++) { salt[i] = (unsigned char)(rand() % 256); }
  166. iv = (unsigned char *)calloc(256, sizeof(char));
  167. key = (unsigned char *)calloc(256, sizeof(char));
  168. r = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha256(), salt, pass_key, strlen((char *)pass_key), 1, key, iv);
  169. if (!r) {
  170. _ret = -5;
  171. goto _encode_b64_cleanup;
  172. }
  173. enc_b = (unsigned char *)calloc(2*LINE_BUFFER_SIZE, sizeof(char));
  174. if (!enc_b) {
  175. _ret = -4;
  176. goto _encode_b64_cleanup;
  177. }
  178. for (i=0; i<8; i++) {
  179. enc_b[i] = _pfx[i];
  180. enc_b[i+8] = salt[i];
  181. }
  182. enc_len = aes_encrypt(msg, strlen((char *)msg), key, iv, enc_b+16);
  183. if (enc_len<=0) {
  184. _ret = -6;
  185. goto _encode_b64_cleanup;
  186. }
  187. enc_len += 16;
  188. b64_sz = Base64encode_len(enc_len);
  189. Base64encode((char *)enc_b64, (char *)enc_b, enc_len);
  190. _ret = b64_sz;
  191. _encode_b64_cleanup:
  192. if (enc_b) { free(enc_b); }
  193. if (key) { free(key); }
  194. if (iv) { free(iv); }
  195. return _ret;
  196. }
  197. // `fqreqr_lookup_decode` uses the public key portion of `fareqr_s`
  198. // to lookup the private pass/key in the file `seedfn`.
  199. // If found, it then proceeds to decrypt and store the encrypted
  200. // credential in `dst_cred`
  201. //
  202. // returns 0 on success
  203. // returns non zero on error
  204. //
  205. int fareqr_lookup_decode(char *seedfn, char *fareqr_s, char *dst_cred) {
  206. int i, n, r, _ret = 0;;
  207. char *p=NULL, *stop_tok=NULL;
  208. char *enc_str = NULL, *dec_str = NULL, *plain_str=NULL,
  209. *pub_key = NULL, *priv_key = NULL;
  210. if ((!seedfn) || (!fareqr_s) || (!dst_cred)) { return -1; }
  211. if (fareqr_s[0] != '@') { return -2; }
  212. stop_tok = strchr(fareqr_s, '%');
  213. if (!stop_tok) { return -3; }
  214. pub_key = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  215. priv_key = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  216. enc_str = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  217. dec_str = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  218. plain_str = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  219. pub_key[0] = priv_key[0] = enc_str[0] = dec_str[0] = plain_str[0] = '\0';
  220. for (i=0, p = (fareqr_s+1); (i<(LINE_BUFFER_SIZE-1)) && (p<stop_tok) && (*p); p++, i++) {
  221. pub_key[i] = *p;
  222. }
  223. pub_key[i] = '\0';
  224. for (n=0, p = (stop_tok+1); (n<(LINE_BUFFER_SIZE-1)) && (*p) && ((*p) != '$'); p++, n++) {
  225. enc_str[n] = *p;
  226. }
  227. enc_str[n] = '\0';
  228. r = fareqr_lookup_seed_secret(seedfn, pub_key, priv_key);
  229. if (r<0) { _ret = r; }
  230. else {
  231. //r = fareqr_decode(fareqr_s, pub_key, priv_key, dst_cred);
  232. r = decode_b64((unsigned char *)dst_cred, (unsigned char *)priv_key, (unsigned char *)enc_str);
  233. if (r<0) { _ret = r; }
  234. }
  235. if (pub_key) { free(pub_key); }
  236. if (priv_key) { free(priv_key); }
  237. if (enc_str) { free(enc_str); }
  238. if (dec_str) { free(dec_str); }
  239. if (plain_str) { free(plain_str); }
  240. return _ret;
  241. }
  242. int fareqr_encode(char *tok_public, char *tok_secret, char *tok_cred, char *fareqr_str) {
  243. int r=0, _ret=0;
  244. uint8_t *dst_data = NULL;
  245. if ((!tok_public) || (!tok_secret) || (!tok_cred) || (!fareqr_str)) { return -9; }
  246. dst_data = (uint8_t *)malloc(sizeof(uint8_t)*LINE_BUFFER_SIZE);
  247. r = encode_b64(dst_data, (unsigned char *)tok_secret, (unsigned char *)tok_cred);
  248. if (r < 0) {
  249. _ret = -1;
  250. goto _fareqr_encode_cleanup;
  251. }
  252. if (fareqr_str) {
  253. snprintf(fareqr_str, LINE_BUFFER_SIZE-1, "@%s%%%s$", tok_public, dst_data);
  254. }
  255. _fareqr_encode_cleanup:
  256. if (dst_data) { free(dst_data); }
  257. return _ret;
  258. }
  259. // depreicated (doing away with one-time pads in favor of AES above)
  260. //
  261. int fareqr_decode(char *fareqr_s, char *check_pub, char *tok_secret, char *dst_cred) {
  262. int n=0, r=0, _ret=0;
  263. char *p, *stop_tok;
  264. int pub_tok_read_len = 0, check_pub_len = 0;
  265. char *enc_str = NULL;
  266. if ((!fareqr_s) || (!dst_cred)) { return -9; }
  267. if (fareqr_s[0] != '@') { return -1; }
  268. stop_tok = strchr(fareqr_s, '%');
  269. if (!stop_tok) { return -2; }
  270. if (!tok_secret) { return -3; }
  271. if (check_pub) {
  272. check_pub_len = strlen(check_pub);
  273. for ( p = (fareqr_s+1); p < stop_tok; p++) {
  274. if (pub_tok_read_len >= check_pub_len) { return -3; }
  275. if ( (*p) != check_pub[pub_tok_read_len] ) { return -4; }
  276. pub_tok_read_len++;
  277. }
  278. }
  279. enc_str = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  280. for (n=0, p = (stop_tok+1); (*p) && ((*p) != '$'); p++, n++) {
  281. enc_str[n] = *p;
  282. }
  283. enc_str[n] = '\0';
  284. r = decode_b64((unsigned char *)dst_cred, (unsigned char *)tok_secret, (unsigned char *)enc_str);
  285. if (r < 0) {
  286. _ret = -1;
  287. goto _fareqr_decode_cleanup;
  288. }
  289. _fareqr_decode_cleanup:
  290. if (enc_str) { free(enc_str); }
  291. return _ret;
  292. }
  293. // return negative on error or not found
  294. // 0 on success (found)
  295. //
  296. int fareqr_lookup_seed_secret(char *seedfn, char *pub, char *priv) {
  297. int i;
  298. FILE *fp;
  299. char buf[LINE_BUFFER_SIZE] = {0};
  300. int pos = 0, ch=0, line_no=0;
  301. char *tok0_ptr=NULL,
  302. *tok1_ptr=NULL;
  303. fp = fopen(seedfn, "r");
  304. if (!fp) { perror(seedfn); return -2;}
  305. while (!feof(fp)) {
  306. ch = fgetc(fp);
  307. // process line if we reach a newline or eof
  308. //
  309. if (feof(fp) || (ch == '\n')) {
  310. // if the line is empty or a comment, skip
  311. //
  312. if ((pos==0) || (buf[0] == '#')) {
  313. }
  314. // get tokens out of line, using ' ' as the
  315. // delimeter
  316. //
  317. else {
  318. tok0_ptr = buf;
  319. tok1_ptr = strchr(buf, ' ');
  320. if (tok1_ptr) {
  321. // tie off the tok0_ptr (public key) for use later
  322. //
  323. *tok1_ptr = '\0';
  324. // start our private key ptr at the start of the
  325. // private key, skipping over whitespace
  326. //
  327. do {
  328. tok1_ptr++;
  329. } while ( (*tok1_ptr) && ((*tok1_ptr) == ' ') );
  330. // Check it against our supplied 'pulbic' key
  331. //
  332. if (strcmp(pub, tok0_ptr)==0) {
  333. // If we've found it, copy it over to the `priv`
  334. // above and return
  335. //
  336. for (i=0; tok1_ptr[i] && (tok1_ptr[i] != ' '); i++) {
  337. priv[i] = tok1_ptr[i];
  338. }
  339. priv[i]='\0';
  340. return 0;
  341. }
  342. }
  343. line_no++;
  344. }
  345. pos=0;
  346. buf[0]='\0';
  347. continue;
  348. }
  349. buf[pos] = ch;
  350. pos++;
  351. buf[pos] = '\0';
  352. }
  353. fclose(fp);
  354. return -1;
  355. }
  356. // to compile:
  357. // gcc -D__FAREQR_MAIN__ fareqr.c b64.c -o fareqr
  358. //
  359. #ifdef __FAREQR_MAIN__
  360. #define FAREQR_VERSION "0.1.0"
  361. void show_version(FILE *ofp) {
  362. fprintf(ofp, "fareqr version %s\n", FAREQR_VERSION);
  363. }
  364. void show_help(FILE *ofp) {
  365. show_version(ofp);
  366. fprintf(ofp, "\nusage:\n\n");
  367. fprintf(ofp, " fareqr encode <pubkey> <privatekey> <str>\n");
  368. fprintf(ofp, " fareqr decode <privatekey> <encstr>\n");
  369. fprintf(ofp, " fareqr dbdecode <qrseedfile> <fareqr>\n");
  370. fprintf(ofp, " fareqr version\n");
  371. fprintf(ofp, " fareqr help\n");
  372. fprintf(ofp, "\n");
  373. fprintf(ofp, "fareqr is a program to help with encoding and decoding 'fareqr' strings.\n");
  374. fprintf(ofp, "\n");
  375. fprintf(ofp, "A fareqr string is of the form:\n");
  376. fprintf(ofp, "\n");
  377. fprintf(ofp, " @<pubkey>%%<aes(privkey,credential)>$\n");
  378. fprintf(ofp, "\n");
  379. fprintf(ofp, "Where `<aes(privkey,credential)>` is the base64 encoded AES encrypted string\n");
  380. fprintf(ofp, "of the credential, encrypted with the privkey.\n");
  381. fprintf(ofp, "\n");
  382. fprintf(ofp, "The <qrseedfile> is a text file of <pubkey> <privkey> pairs.\n");
  383. fprintf(ofp, "\n");
  384. fprintf(ofp, "Here is some example usage:\n");
  385. fprintf(ofp, "\n");
  386. fprintf(ofp, " $ fareqr encode 'wu9XouSh' 'ohNgizahkephain3aosoh2AeH1aethoo4cie6oiSaezimaighai2eiVaefahfien' ';123456789060535?'\n");
  387. fprintf(ofp, " @wu9XouSh%%U2FsdGVkX19nxmlzUf9K7GAgplhbmU4tcFYYa/Xz6oq0XrxSYTbBOA2yffAi7A0z$\n");
  388. fprintf(ofp, " $ fareqr decode 'ohNgizahkephain3aosoh2AeH1aethoo4cie6oiSaezimaighai2eiVaefahfien' '@wu9XouSh%%U2FsdGVkX19nxmlzUf9K7GAgplhbmU4tcFYYa/Xz6oq0XrxSYTbBOA2yffAi7A0z$'\n");
  389. fprintf(ofp, " ;123456789060535?\n");
  390. fprintf(ofp, " $ echo 'wu9XouSh ohNgizahkephain3aosoh2AeH1aethoo4cie6oiSaezimaighai2eiVaefahfien' > ./qr.seed\n");
  391. fprintf(ofp, " $ fareqr dbdecode ./qr.seed '@wu9XouSh%%U2FsdGVkX19nxmlzUf9K7GAgplhbmU4tcFYYa/Xz6oq0XrxSYTbBOA2yffAi7A0z$'\n");
  392. fprintf(ofp, " ;123456789060535?\n");
  393. fprintf(ofp, "\n");
  394. fprintf(ofp, "Where 'wu9XouSh' is the public key, 'ohNgizahkephain3aosoh2AeH1aethoo4cie6oiSaezimaighai2eiVaefahfien' is the private key and\n");
  395. fprintf(ofp, "';123456789060535?' is the credential information to be encoded.\n");
  396. fprintf(ofp, "\n");
  397. fprintf(ofp, "\n");
  398. fflush(ofp);
  399. }
  400. /*
  401. *
  402. * quick test/start:
  403. *
  404. * $ fareqr encode 'wu9XouSh' 'ohNgizahkephain3aosoh2AeH1aethoo4cie6oiSaezimaighai2eiVaefahfien' ';123456789060535?'
  405. * @wu9XouSh%VFl8VF1PV19TXEBeUVxdBl4=
  406. *
  407. * $ fareqr decode 'ohNgizahkephain3aosoh2AeH1aethoo4cie6oiSaezimaighai2eiVaefahfien' '@wu9XouSh%VFl8VF1PV19TXEBeUVxdBl4=$'
  408. * ;123456789060535?
  409. *
  410. * $ fareqr dbdecode '@wu9XouSh%VFl8VF1PV19TXEBeUVxdBl4=$'
  411. * ;123456789060535?
  412. *
  413. */
  414. int main(int argc, char **argv) {
  415. int i, r;
  416. char *tok_public = NULL,
  417. *tok_secret = NULL,
  418. *tok_cred = NULL,
  419. *fareqr_str = NULL;
  420. uint8_t x,y,z;
  421. uint8_t *src_data = NULL, *dst_data = NULL;
  422. int src_data_n = 0, dst_data_n = 0;
  423. char *fn = NULL;
  424. if (argc <= 1) {
  425. show_help(stderr);
  426. exit(1);
  427. }
  428. if (strcmp(argv[1], "encode")==0) {
  429. if (argc>2) {
  430. tok_public = strdup(argv[2]);
  431. if (argc>3) {
  432. tok_secret = strdup(argv[3]);
  433. if (argc>4) {
  434. tok_cred = strdup(argv[4]);
  435. }
  436. }
  437. }
  438. if ((!tok_public) || (!tok_secret) || (!tok_cred)) {
  439. show_help(stderr);
  440. if (tok_public) { free(tok_public); }
  441. if (tok_secret) { free(tok_secret); }
  442. if (tok_cred) { free(tok_cred); }
  443. exit(2);
  444. }
  445. fareqr_str = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  446. r = fareqr_encode(tok_public, tok_secret, tok_cred, fareqr_str);
  447. if (r==0) {
  448. printf("%s\n", fareqr_str);
  449. }
  450. }
  451. else if (strcmp(argv[1], "decode")==0) {
  452. if (argc>2) {
  453. tok_secret = strdup(argv[2]);
  454. if (argc>3) {
  455. fareqr_str = strdup(argv[3]);
  456. }
  457. }
  458. tok_cred = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  459. tok_cred[0] = '0';
  460. r = fareqr_decode(fareqr_str, tok_public, tok_secret, tok_cred);
  461. if (r<0) {
  462. fprintf(stderr, "error, failed to decode qr fare string (%i)\n", r);
  463. }
  464. else {
  465. printf("%s\n", tok_cred);
  466. }
  467. }
  468. else if (strcmp(argv[1], "dbdecode")==0) {
  469. if (argc>2) {
  470. fn = strdup(argv[2]);
  471. if (argc>3) {
  472. fareqr_str = strdup(argv[3]);
  473. }
  474. }
  475. tok_cred = (char *)malloc(sizeof(char)*LINE_BUFFER_SIZE);
  476. tok_cred[0] = '0';
  477. r = fareqr_lookup_decode(fn, fareqr_str, tok_cred);
  478. if (r<0) {
  479. fprintf(stderr, "could not decode '%s' with db file '%s', exiting (got %i)\n",
  480. fareqr_str, fn, r);
  481. }
  482. else {
  483. printf("%s\n", tok_cred);
  484. }
  485. }
  486. // test out our AES encryption
  487. //
  488. else if (strcmp(argv[1], "aes-decode")==0) {
  489. if (argc>2) {
  490. tok_secret = strdup(argv[2]);
  491. if (argc>3) {
  492. fareqr_str = strdup(argv[3]);
  493. }
  494. }
  495. tok_cred = (unsigned char *)calloc(LINE_BUFFER_SIZE, sizeof(char));
  496. r = decode_b64(tok_cred, tok_secret, fareqr_str);
  497. if (r<0) {
  498. fprintf(stderr, "could not decode aes base64 string (AES CBC 256, sha256 md) (got %i)\n", r);
  499. }
  500. else {
  501. printf("%s\n", tok_cred);
  502. }
  503. }
  504. // test out our AES encryption
  505. //
  506. else if (strcmp(argv[1], "aes-encode")==0) {
  507. if (argc>2) {
  508. tok_secret = strdup(argv[2]);
  509. if (argc>3) {
  510. tok_cred = strdup(argv[3]);
  511. }
  512. }
  513. fareqr_str = (unsigned char *)calloc(2*LINE_BUFFER_SIZE, sizeof(char));
  514. r = encode_b64(fareqr_str, tok_secret, tok_cred);
  515. if (r<0) {
  516. fprintf(stderr, "could not encode aes base64 string (AES CBC 256, sha256 md) (got %i)\n", r);
  517. }
  518. else {
  519. printf("%s\n", fareqr_str);
  520. }
  521. }
  522. else if (strcmp(argv[1], "help")==0) {
  523. show_help(stdout);
  524. exit(0);
  525. }
  526. else if (strcmp(argv[1], "version")==0) {
  527. show_version(stdout);
  528. exit(0);
  529. }
  530. else {
  531. fprintf(stderr, "unknown operation '%s'\n", argv[1]);
  532. show_help(stderr);
  533. exit(3);
  534. }
  535. if (tok_public) { free(tok_public); }
  536. if (tok_secret) { free(tok_secret); }
  537. if (tok_cred) { free(tok_cred); }
  538. if (fareqr_str) { free(fareqr_str); }
  539. if (src_data) { free(src_data); }
  540. if (dst_data) { free(dst_data); }
  541. if (fn) { free(fn); }
  542. }
  543. #endif