libidav/crypto.c

changeset 689
b1f7d83f6e69
parent 688
d405d2ac78e6
child 690
ce253cfb9127
equal deleted inserted replaced
688:d405d2ac78e6 689:b1f7d83f6e69
1016 dec->stream = stream; 1016 dec->stream = stream;
1017 dec->write = write_func; 1017 dec->write = write_func;
1018 dec->key = key; 1018 dec->key = key;
1019 dec->init = 0; 1019 dec->init = 0;
1020 dec->ivpos = 0; 1020 dec->ivpos = 0;
1021 1021
1022 return dec; 1022 return dec;
1023 } 1023 }
1024 1024
1025 static void aes_decrypter_init(AESDecrypter *dec) { 1025 static void aes_decrypter_init(AESDecrypter *dec) {
1026 if(cng_init_key(&dec->ctx.hAlg, &dec->ctx.hKey, &dec->ctx.pbKeyObject, dec->key)) { 1026 if(cng_init_key(&dec->ctx.hAlg, &dec->ctx.hKey, &dec->ctx.pbKeyObject, dec->key)) {
1032 } 1032 }
1033 1033
1034 size_t aes_write(const void *buf, size_t s, size_t n, AESDecrypter *dec) { 1034 size_t aes_write(const void *buf, size_t s, size_t n, AESDecrypter *dec) {
1035 int len = s*n; 1035 int len = s*n;
1036 if(!dec->init) { 1036 if(!dec->init) {
1037 dec->init = 1;
1038
1037 size_t n = 16 - dec->ivpos; 1039 size_t n = 16 - dec->ivpos;
1038 size_t cp = n > len ? len : n; 1040 size_t cp = n > len ? len : n;
1039 memcpy(dec->ivtmp + dec->ivpos, buf, cp); 1041 memcpy(dec->ivtmp + dec->ivpos, buf, cp);
1040 dec->ivpos += cp; 1042 dec->ivpos += cp;
1041 if(dec->ivpos >= 16) { 1043 if(dec->ivpos >= 16) {
1050 } 1052 }
1051 1053
1052 // the cipher text must be a multiply of 16 1054 // the cipher text must be a multiply of 16
1053 // remaining bytes are stored in ctx.buf and must be added to cibuf 1055 // remaining bytes are stored in ctx.buf and must be added to cibuf
1054 // the next time 1056 // the next time
1055 size_t cbufalloc = len + 32; 1057 size_t cbufalloc = len + 64;
1056 ULONG clen = 0; 1058 ULONG clen = 0;
1057 char *cbuf = malloc(cbufalloc); 1059 char *cbuf = malloc(cbufalloc);
1058 1060
1059 // add previous remaining bytes 1061 // add previous remaining bytes
1060 if(dec->ctx.buflen > 0) { 1062 if(dec->ctx.buflen > 0) {
1065 memcpy(cbuf + clen, buf, len); 1067 memcpy(cbuf + clen, buf, len);
1066 clen += len; 1068 clen += len;
1067 1069
1068 // check if the message fits the blocksize 1070 // check if the message fits the blocksize
1069 int remaining = clen % 16; 1071 int remaining = clen % 16;
1070 if(remaining > 0) { 1072 if(remaining == 0) {
1071 // add remaining bytes to ctx.buf for the next aes_write run 1073 // decrypt last block next time, or in aes_decrypter_shutdown
1072 clen -= remaining; 1074 // this makes sure, that shutdown always decrypts the last block
1073 memcpy(dec->ctx.buf, cbuf + clen - remaining, remaining); 1075 // with BCRYPT_BLOCK_PADDING flag
1074 } 1076 remaining = 16;
1077 }
1078
1079 // add remaining bytes to ctx.buf for the next aes_write run
1080 clen -= remaining;
1081 memcpy(dec->ctx.buf, cbuf + clen, remaining);
1075 dec->ctx.buflen = remaining; 1082 dec->ctx.buflen = remaining;
1076 1083
1077 // ready to decrypt the message 1084 // ready to decrypt the message
1078 ULONG outlen = clen + 32; 1085 ULONG outlen = clen + 32;
1079 unsigned char *out = malloc(outlen); 1086 unsigned char *out = malloc(outlen);
1080 1087
1081 // decrypt 1088 // decrypt
1082 if(clen > 0) { 1089 if(clen > 0) {
1083 if(BCryptDecrypt(dec->ctx.hKey, cbuf, clen, NULL, dec->ctx.pbIV, 16, out, outlen, &outlen, BCRYPT_BLOCK_PADDING)) { 1090 ULONG enc_len = 0;
1084 fprintf(stderr, "Error: BCryptDecrypt failed\n"); 1091 ULONG status = BCryptDecrypt(dec->ctx.hKey, cbuf, clen, NULL, dec->ctx.pbIV, 16, out, outlen, &enc_len, 0);
1092 if(status > 0) {
1093 fprintf(stderr, "Error: BCryptDecrypt failed: 0x%X\n", status);
1085 free(out); 1094 free(out);
1086 free(cbuf); 1095 free(cbuf);
1087 return 0; 1096 return 0;
1088 } 1097 }
1098 outlen = enc_len;
1089 } 1099 }
1090 1100
1091 // write decrypted data to the output stream and update the hash 1101 // write decrypted data to the output stream and update the hash
1092 dec->write(out, 1, outlen, dec->stream); 1102 dec->write(out, 1, outlen, dec->stream);
1093 BCryptHashData(dec->sha256.hHash, out, outlen, 0); 1103 BCryptHashData(dec->sha256.hHash, out, outlen, 0);
1104
1094 free(out); 1105 free(out);
1095 free(cbuf); 1106 free(cbuf);
1096 1107
1097 return (s*n) / s; 1108 return (s*n) / s;
1098 } 1109 }
1099 1110
1100 void aes_decrypter_shutdown(AESDecrypter *dec) { 1111 void aes_decrypter_shutdown(AESDecrypter *dec) {
1101 if(dec->init && dec->ctx.buflen > 0) { 1112 if(dec->init && dec->ctx.buflen > 0) {
1102 ULONG outlen = 64; 1113 ULONG outlen = 64;
1103 char out[64]; 1114 char out[64];
1104 if(BCryptDecrypt(dec->ctx.hKey, dec->ctx.buf, dec->ctx.buflen, NULL, dec->ctx.pbIV, 16, out, outlen, &outlen, BCRYPT_BLOCK_PADDING)) { 1115 if(BCryptDecrypt(dec->ctx.hKey, dec->ctx.buf, dec->ctx.buflen, NULL, dec->ctx.pbIV, 16, out, outlen, &outlen, BCRYPT_BLOCK_PADDING)) {
1105 fprintf(stderr, "Error: BCryptDecrypt failed\n"); 1116 fprintf(stderr, "Error: BCryptDecrypt failed\n");
1106 return; 1117 return;

mercurial