aescbc.c 4.0 KB

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