aescbc.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /* encrypt file by writing
  10. v2hdr,
  11. 16byte initialization vector,
  12. AES-CBC(key, random | file),
  13. HMAC_SHA1(md5(key), AES-CBC(random | file))
  14. */
  15. #include <u.h>
  16. #include <libc.h>
  17. #include <bio.h>
  18. #include <mp.h>
  19. #include <libsec.h>
  20. #include <authsrv.h>
  21. extern char* getpassm(char*);
  22. enum{ CHK = 16, BUF = 4096 };
  23. uint8_t v2hdr[AESbsize+1] = "AES CBC SHA1 2\n";
  24. Biobuf bin;
  25. Biobuf bout;
  26. void
  27. safewrite(uint8_t *buf, int n)
  28. {
  29. if(Bwrite(&bout, buf, n) != n)
  30. sysfatal("write error");
  31. }
  32. void
  33. saferead(uint8_t *buf, int n)
  34. {
  35. if(Bread(&bin, buf, n) != n)
  36. sysfatal("read error");
  37. }
  38. int
  39. main(int argc, char **argv)
  40. {
  41. int encrypt = 0; /* 0=decrypt, 1=encrypt */
  42. int n, nkey, pass_stdin = 0, pass_nvram = 0;
  43. char *pass;
  44. unsigned char key[AESmaxkey], key2[SHA1dlen];
  45. unsigned char buf[BUF+SHA1dlen]; /* assumption: CHK <= SHA1dlen */
  46. AESstate aes;
  47. DigestState *dstate;
  48. Nvrsafe nvr;
  49. ARGBEGIN{
  50. case 'e':
  51. encrypt = 1;
  52. break;
  53. case 'i':
  54. pass_stdin = 1;
  55. break;
  56. case 'n':
  57. pass_nvram = 1;
  58. break;
  59. }ARGEND;
  60. if(argc!=0){
  61. fprint(2,"usage: %s -d < cipher.aes > clear.txt\n", argv0);
  62. fprint(2," or: %s -e < clear.txt > cipher.aes\n", argv0);
  63. exits("usage");
  64. }
  65. Binit(&bin, 0, OREAD);
  66. Binit(&bout, 1, OWRITE);
  67. if(pass_stdin){
  68. n = readn(3, buf, (sizeof buf)-1);
  69. if(n < 1)
  70. exits("usage: echo password |[3=1] auth/aescbc -i ...");
  71. buf[n] = 0;
  72. while(buf[n-1] == '\n')
  73. buf[--n] = 0;
  74. }else if(pass_nvram){
  75. if(readnvram(&nvr, 0) < 0)
  76. exits("readnvram: %r");
  77. strecpy((char*)buf, (char*)buf+sizeof buf, (char*)nvr.config);
  78. n = strlen((char*)buf);
  79. }else{
  80. pass = getpassm("aescbc key:");
  81. n = strlen(pass);
  82. if(n >= BUF)
  83. exits("key too long");
  84. strcpy((char*)buf, pass);
  85. memset(pass, 0, n);
  86. free(pass);
  87. }
  88. if(n <= 0)
  89. sysfatal("no key");
  90. dstate = sha1((unsigned char*)"aescbc file", 11, nil, nil);
  91. sha1(buf, n, key2, dstate);
  92. memcpy(key, key2, 16);
  93. nkey = 16;
  94. md5(key, nkey, key2, 0); /* so even if HMAC_SHA1 is broken, encryption key is protected */
  95. if(encrypt){
  96. safewrite(v2hdr, AESbsize);
  97. genrandom(buf,2*AESbsize); /* CBC is semantically secure if IV is unpredictable. */
  98. setupAESstate(&aes, key, nkey, buf); /* use first AESbsize bytes as IV */
  99. aesCBCencrypt(buf+AESbsize, AESbsize, &aes); /* use second AESbsize bytes as initial plaintext */
  100. safewrite(buf, 2*AESbsize);
  101. dstate = hmac_sha1(buf+AESbsize, AESbsize, key2, MD5dlen, 0, 0);
  102. for(;;){
  103. n = Bread(&bin, buf, BUF);
  104. if(n < 0)
  105. sysfatal("read error");
  106. aesCBCencrypt(buf, n, &aes);
  107. safewrite(buf, n);
  108. dstate = hmac_sha1(buf, n, key2, MD5dlen, 0, dstate);
  109. if(n < BUF)
  110. break; /* EOF */
  111. }
  112. hmac_sha1(0, 0, key2, MD5dlen, buf, dstate);
  113. safewrite(buf, SHA1dlen);
  114. }else{ /* decrypt */
  115. saferead(buf, AESbsize);
  116. if(memcmp(buf, v2hdr, AESbsize) == 0){
  117. saferead(buf, 2*AESbsize); /* read IV and random initial plaintext */
  118. setupAESstate(&aes, key, nkey, buf);
  119. dstate = hmac_sha1(buf+AESbsize, AESbsize, key2, MD5dlen, 0, 0);
  120. aesCBCdecrypt(buf+AESbsize, AESbsize, &aes);
  121. saferead(buf, SHA1dlen);
  122. while((n = Bread(&bin, buf+SHA1dlen, BUF)) > 0){
  123. dstate = hmac_sha1(buf, n, key2, MD5dlen, 0, dstate);
  124. aesCBCdecrypt(buf, n, &aes);
  125. safewrite(buf, n);
  126. memmove(buf, buf+n, SHA1dlen); /* these bytes are not yet decrypted */
  127. }
  128. hmac_sha1(0, 0, key2, MD5dlen, buf+SHA1dlen, dstate);
  129. if(memcmp(buf, buf+SHA1dlen, SHA1dlen) != 0)
  130. sysfatal("decrypted file failed to authenticate");
  131. }else{ /* compatibility with past mistake */
  132. // if file was encrypted with bad aescbc use this:
  133. // memset(key, 0, AESmaxkey);
  134. // else assume we're decrypting secstore files
  135. setupAESstate(&aes, key, AESbsize, buf);
  136. saferead(buf, CHK);
  137. aesCBCdecrypt(buf, CHK, &aes);
  138. while((n = Bread(&bin, buf+CHK, BUF)) > 0){
  139. aesCBCdecrypt(buf+CHK, n, &aes);
  140. safewrite(buf, n);
  141. memmove(buf, buf+n, CHK);
  142. }
  143. if(memcmp(buf, "XXXXXXXXXXXXXXXX", CHK) != 0)
  144. sysfatal("decrypted file failed to authenticate");
  145. }
  146. }
  147. exits("");
  148. return 1; /* keep other compilers happy */
  149. }