libidav/crypto.c

changeset 688
d405d2ac78e6
parent 625
e1a85fbf68f9
child 689
b1f7d83f6e69
equal deleted inserted replaced
687:9922a349a61a 688:d405d2ac78e6
448 448
449 #endif 449 #endif
450 450
451 451
452 /* -------------------- Apple Crypto Functions -------------------- */ 452 /* -------------------- Apple Crypto Functions -------------------- */
453 #ifdef __APPLE__ 453 #ifdef DAV_CRYPTO_COMMON_CRYPTO
454 454
455 #define RANDOM_BUFFER_LENGTH 256 455 #define RANDOM_BUFFER_LENGTH 256
456 static char randbuf[RANDOM_BUFFER_LENGTH]; 456 static char randbuf[RANDOM_BUFFER_LENGTH];
457 static int rbufpos = RANDOM_BUFFER_LENGTH; 457 static int rbufpos = RANDOM_BUFFER_LENGTH;
458 458
889 return key; 889 return key;
890 } 890 }
891 891
892 #endif 892 #endif
893 893
894 /* -------------------- Windows Crypto Functions -------------------- */
895 #ifdef DAV_CRYPTO_CNG
896
897 static void cng_cleanup(BCRYPT_ALG_HANDLE hAesAlg, BCRYPT_KEY_HANDLE hKey, BCRYPT_HASH_HANDLE hHash, void *pbObject) {
898 if(hAesAlg) {
899 BCryptCloseAlgorithmProvider(hAesAlg,0);
900 }
901 if(hKey) {
902 BCryptDestroyKey(hKey);
903 }
904 if(hHash) {
905 BCryptDestroyHash(hHash);
906 }
907 if(pbObject) {
908 free(pbObject);
909 }
910 }
911
912 static int cng_init_key(BCRYPT_ALG_HANDLE *alg, BCRYPT_KEY_HANDLE *key, void **keyobj, DavKey *aesKey) {
913 BCRYPT_ALG_HANDLE hAesAlg = NULL;
914 BCRYPT_KEY_HANDLE hKey = NULL;
915
916 void *pbKeyObject = NULL;
917 ULONG keyObjectLength = 0;
918
919 ULONG result = 0;
920
921 // check DavKey and get AES key length
922 if(!aesKey) {
923 return 1;
924 }
925
926 ULONG aesKeyLength = 0;
927 if(aesKey->type == DAV_KEY_AES128) {
928 aesKeyLength = 16;
929 } else if(aesKey->type == DAV_KEY_AES256) {
930 aesKeyLength = 32;
931 }
932 if(aesKeyLength > aesKey->length || !aesKey->data) {
933 // invalid DavKey
934 return 1;
935 }
936
937 // initialize BCrypt stuff
938 if(BCryptOpenAlgorithmProvider(&hAesAlg, BCRYPT_AES_ALGORITHM, NULL, 0)) {
939 fprintf(stderr, "Error: BCryptOpenAlgorithmProvider failed\n");
940 return 1;
941 }
942
943 if(BCryptGetProperty(hAesAlg, BCRYPT_OBJECT_LENGTH, (PUCHAR)&keyObjectLength, sizeof(DWORD), &result, 0)) {
944 fprintf(stderr, "Error: BCrypt: Cannot get BCRYPT_OBJECT_LENGTH\n");
945 cng_cleanup(hAesAlg, hKey, NULL, pbKeyObject);
946 return 1;
947 }
948
949 if(BCryptSetProperty(hAesAlg, BCRYPT_CHAINING_MODE, (PBYTE)BCRYPT_CHAIN_MODE_CBC, sizeof(BCRYPT_CHAIN_MODE_CBC), 0)) {
950 fprintf(stderr, "Error: BCrypt: Cannot set CBC mode\n");
951 cng_cleanup(hAesAlg, hKey, NULL, pbKeyObject);
952 return 1;
953 }
954
955 pbKeyObject = calloc(1, keyObjectLength);
956 if(!pbKeyObject) {
957 cng_cleanup(hAesAlg, hKey, NULL, pbKeyObject);
958 return 1;
959 }
960
961 // init key
962 if(BCryptGenerateSymmetricKey(hAesAlg, &hKey, pbKeyObject, keyObjectLength, aesKey->data, aesKeyLength, 0)) {
963 fprintf(stderr, "Error: BCrypt: Cannot set key\n");
964 cng_cleanup(hAesAlg, hKey, NULL, pbKeyObject);
965 return 1;
966 }
967
968 *alg = hAesAlg;
969 *key = hKey;
970 *keyobj = pbKeyObject;
971
972 return 0;
973 }
974
975 static int cng_hash_init(WinBCryptSHACTX *ctx) {
976 if(BCryptOpenAlgorithmProvider(&ctx->hAlg, BCRYPT_SHA256_ALGORITHM, NULL, 0)) {
977 fprintf(stderr, "Error: BCryptOpenAlgorithmProvider failed\n");
978 return 1;
979 }
980
981 ULONG hashObjectLen;
982 ULONG result;
983 if(BCryptGetProperty(ctx->hAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&hashObjectLen, sizeof(DWORD), &result, 0)) {
984 cng_cleanup(ctx->hAlg, NULL, NULL, NULL);
985 return 1;
986 }
987
988 ctx->pbHashObject = calloc(1, hashObjectLen);
989
990 if(BCryptCreateHash(ctx->hAlg, &ctx->hHash, ctx->pbHashObject, hashObjectLen, NULL, 0, 0)) {
991 cng_cleanup(ctx->hAlg, NULL, ctx->hHash, ctx->pbHashObject);
992 return 1;
993 }
994
995 return 0;
996 }
997
998
999 int dav_rand_bytes(unsigned char *buf, size_t len) {
1000 if(BCryptGenRandom(NULL, (unsigned char*)buf, (ULONG)len, BCRYPT_USE_SYSTEM_PREFERRED_RNG)) {
1001 return 1;
1002 }
1003 return 0;
1004 }
1005
1006 AESDecrypter* aes_decrypter_new(DavKey *key, void *stream, dav_write_func write_func) {
1007 AESDecrypter *dec = calloc(1, sizeof(AESDecrypter));
1008 if(!dec) {
1009 return NULL;
1010 }
1011 if(cng_hash_init(&dec->sha256)) {
1012 free(dec);
1013 return NULL;
1014 }
1015
1016 dec->stream = stream;
1017 dec->write = write_func;
1018 dec->key = key;
1019 dec->init = 0;
1020 dec->ivpos = 0;
1021
1022 return dec;
1023 }
1024
1025 static void aes_decrypter_init(AESDecrypter *dec) {
1026 if(cng_init_key(&dec->ctx.hAlg, &dec->ctx.hKey, &dec->ctx.pbKeyObject, dec->key)) {
1027 fprintf(stderr, "Error: cng_init_key failed\n");
1028 exit(-1);
1029 }
1030 // copy iv
1031 memcpy(dec->ctx.pbIV, dec->ivtmp, 16);
1032 }
1033
1034 size_t aes_write(const void *buf, size_t s, size_t n, AESDecrypter *dec) {
1035 int len = s*n;
1036 if(!dec->init) {
1037 size_t n = 16 - dec->ivpos;
1038 size_t cp = n > len ? len : n;
1039 memcpy(dec->ivtmp + dec->ivpos, buf, cp);
1040 dec->ivpos += cp;
1041 if(dec->ivpos >= 16) {
1042 aes_decrypter_init(dec);
1043 }
1044 if(len == cp) {
1045 return len;
1046 } else {
1047 buf = (char*)buf + cp;
1048 len -= cp;
1049 }
1050 }
1051
1052 // the cipher text must be a multiply of 16
1053 // remaining bytes are stored in ctx.buf and must be added to cibuf
1054 // the next time
1055 size_t cbufalloc = len + 32;
1056 ULONG clen = 0;
1057 char *cbuf = malloc(cbufalloc);
1058
1059 // add previous remaining bytes
1060 if(dec->ctx.buflen > 0) {
1061 memcpy(cbuf, dec->ctx.buf, dec->ctx.buflen);
1062 clen = dec->ctx.buflen;
1063 }
1064 // add current bytes
1065 memcpy(cbuf + clen, buf, len);
1066 clen += len;
1067
1068 // check if the message fits the blocksize
1069 int remaining = clen % 16;
1070 if(remaining > 0) {
1071 // add remaining bytes to ctx.buf for the next aes_write run
1072 clen -= remaining;
1073 memcpy(dec->ctx.buf, cbuf + clen - remaining, remaining);
1074 }
1075 dec->ctx.buflen = remaining;
1076
1077 // ready to decrypt the message
1078 ULONG outlen = clen + 32;
1079 unsigned char *out = malloc(outlen);
1080
1081 // decrypt
1082 if(clen > 0) {
1083 if(BCryptDecrypt(dec->ctx.hKey, cbuf, clen, NULL, dec->ctx.pbIV, 16, out, outlen, &outlen, BCRYPT_BLOCK_PADDING)) {
1084 fprintf(stderr, "Error: BCryptDecrypt failed\n");
1085 free(out);
1086 free(cbuf);
1087 return 0;
1088 }
1089 }
1090
1091 // write decrypted data to the output stream and update the hash
1092 dec->write(out, 1, outlen, dec->stream);
1093 BCryptHashData(dec->sha256.hHash, out, outlen, 0);
1094 free(out);
1095 free(cbuf);
1096
1097 return (s*n) / s;
1098 }
1099
1100 void aes_decrypter_shutdown(AESDecrypter *dec) {
1101 if(dec->init && dec->ctx.buflen > 0) {
1102 ULONG outlen = 64;
1103 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)) {
1105 fprintf(stderr, "Error: BCryptDecrypt failed\n");
1106 return;
1107 }
1108 dec->write(out, 1, outlen, dec->stream);
1109 BCryptHashData(dec->sha256.hHash, out, outlen, 0);
1110 }
1111 }
1112
1113 void aes_decrypter_close(AESDecrypter *dec) {
1114 cng_cleanup(dec->ctx.hAlg, dec->ctx.hKey, NULL, dec->ctx.pbKeyObject);
1115 cng_cleanup(dec->sha256.hAlg, NULL, dec->sha256.hHash, dec->sha256.pbHashObject);
1116 free(dec);
1117 }
1118
1119 AESEncrypter* aes_encrypter_new(DavKey *key, void *stream, dav_read_func read_func, dav_seek_func seek_func) {
1120 unsigned char *iv = malloc(16);
1121 if(dav_rand_bytes(iv, 16)) {
1122 free(iv);
1123 return NULL;
1124 }
1125
1126 AESEncrypter *enc = calloc(1, sizeof(AESEncrypter));
1127 if(cng_hash_init(&enc->sha256)) {
1128 free(iv);
1129 free(enc);
1130 return NULL;
1131 }
1132
1133 enc->stream = stream;
1134 enc->read = read_func;
1135 enc->seek = seek_func;
1136 enc->tmp = NULL;
1137 enc->tmplen = 0;
1138 enc->tmpoff = 0;
1139 enc->end = 0;
1140 enc->iv = iv;
1141 enc->ivlen = 0;
1142
1143 if(cng_init_key(&enc->ctx.hAlg, &enc->ctx.hKey, &enc->ctx.pbKeyObject, key)) {
1144 fprintf(stderr, "Error: cng_init_key failed\n");
1145 exit(-1);
1146 }
1147
1148 enc->ctx.buflen = 0;
1149 memcpy(enc->ctx.pbIV, iv, 16);
1150
1151 return enc;
1152 }
1153
1154 size_t aes_read(void *buf, size_t s, size_t n, AESEncrypter *enc) {
1155 size_t len = s*n;
1156 size_t nread = 0;
1157
1158 if(enc->tmp) {
1159 // the temp buffer contains bytes that are already encrypted, but
1160 // the last aes_read had not enough read buffer space
1161
1162 // in case we have a tmp buf, we just return this
1163 size_t tmp_diff = enc->tmplen - enc->tmpoff;
1164 size_t cp_len = tmp_diff > len ? len : tmp_diff;
1165 memcpy(buf, enc->tmp + enc->tmpoff, cp_len);
1166 enc->tmpoff += cp_len;
1167 if(enc->tmpoff >= enc->tmplen) {
1168 free(enc->tmp);
1169 enc->tmp = NULL;
1170 enc->tmplen = 0;
1171 enc->tmpoff = 0;
1172 }
1173 return cp_len / s;
1174 }
1175
1176 if(enc->ivlen < 16) {
1177 size_t copy_iv_len = 16 - enc->ivlen;
1178 copy_iv_len = len > copy_iv_len ? copy_iv_len : len;
1179
1180 memcpy(buf, enc->iv, copy_iv_len);
1181 buf += copy_iv_len;
1182 len -= copy_iv_len;
1183 nread = copy_iv_len;
1184
1185 enc->ivlen += copy_iv_len;
1186
1187 if(len == 0) {
1188 return copy_iv_len / s;
1189 }
1190 }
1191
1192 if(enc->end) {
1193 return 0;
1194 }
1195
1196 size_t remaining = len % 16;
1197 len -= remaining;
1198
1199 size_t inalloc = len;
1200 ULONG inlen = 0;
1201 unsigned char *in = malloc(inalloc);
1202
1203 // fill the input buffer
1204 while(inlen < inalloc) {
1205 size_t r = enc->read(in + inlen, 1, inalloc - inlen, enc->stream);
1206 if(r == 0) {
1207 enc->end = 1;
1208 break;
1209 }
1210 inlen += r;
1211 }
1212
1213 if(inlen == 0) {
1214 return nread / s;
1215 }
1216
1217 // hash read data
1218 BCryptHashData(enc->sha256.hHash, in, inlen, 0);
1219
1220 // create output buffer
1221 ULONG outalloc = inlen + 16;
1222 ULONG outlen = 0;
1223 char *out = malloc(outalloc);
1224
1225 // encrypt
1226 if(BCryptEncrypt(enc->ctx.hKey, in, inlen, NULL, enc->ctx.pbIV, 16, out, outalloc, &outlen, BCRYPT_BLOCK_PADDING)) {
1227 fprintf(stderr, "Error: BCryptEncrypt failed\n");
1228 }
1229
1230 // check if the output fits in buf, if not, save the remaining bytes in tmp
1231 if(outlen > len) {
1232 size_t tmplen = outlen - len;
1233 char *tmp = malloc(tmplen);
1234 memcpy(tmp, out+len, tmplen);
1235
1236 enc->tmp = tmp;
1237 enc->tmplen = tmplen;
1238 enc->tmpoff = 0;
1239
1240 outlen = len;
1241 }
1242
1243 // fill read buffer and return
1244 memcpy(buf, out, outlen);
1245 nread += outlen;
1246
1247 free(in);
1248 free(out);
1249
1250 return nread / s;
1251 }
1252
1253 void aes_encrypter_close(AESEncrypter *enc) {
1254 enc->end = 1;
1255 }
1256
1257 int aes_encrypter_reset(AESEncrypter *enc, curl_off_t offset, int origin) {
1258 if(origin != SEEK_SET || offset != 0 || !enc->seek) {
1259 return CURL_SEEKFUNC_CANTSEEK;
1260 }
1261
1262 enc->ivlen = 0;
1263 memcpy(enc->ctx.pbIV, enc->iv, 16);
1264 if(enc->seek(enc->stream, 0, SEEK_SET) != 0) {
1265 return CURL_SEEKFUNC_FAIL;
1266 }
1267 return CURL_SEEKFUNC_OK;
1268 }
1269
1270 char* aes_encrypt(const char *in, size_t len, DavKey *key) {
1271 // create random IV
1272 char iv[16];
1273 if(dav_rand_bytes(iv, 16)) {
1274 return NULL;
1275 }
1276
1277 // initialize bcrypt stuff
1278 BCRYPT_ALG_HANDLE hAlg = NULL;
1279 BCRYPT_KEY_HANDLE hKey = NULL;
1280 void *pbKeyObject = NULL;
1281 if(cng_init_key(&hAlg, &hKey, &pbKeyObject, key)) {
1282 return NULL;
1283 }
1284
1285 // create output buffer
1286 ULONG outlen = len + 128;
1287 char *out = malloc(outlen);
1288
1289 // the output must start with the IV
1290 memcpy(out, iv, 16);
1291 char *encbuf = out + 16;
1292 ULONG enclen = outlen - 16;
1293 ULONG encoutlen = 0;
1294
1295 // encrypt
1296 if(BCryptEncrypt(hKey, (PUCHAR)in, len, NULL, (PUCHAR)iv, 16, encbuf, enclen, &encoutlen, BCRYPT_BLOCK_PADDING)) {
1297 fprintf(stderr, "Error: BCryptEncrypt failed\n");
1298 cng_cleanup(hAlg, hKey, NULL, pbKeyObject);
1299 free(out);
1300 return NULL;
1301 }
1302
1303 outlen = encoutlen + 16; // length of encrypted data + 16 bytes IV
1304
1305 // base64 encode
1306 char *outstr = util_base64encode(out, outlen);
1307
1308 cng_cleanup(hAlg, hKey, NULL, pbKeyObject);
1309 free(out);
1310
1311 return outstr;
1312 }
1313
1314 char* aes_decrypt(const char *in, size_t *len, DavKey *key) {
1315 BCRYPT_ALG_HANDLE hAlg = NULL;
1316 BCRYPT_KEY_HANDLE hKey = NULL;
1317 void *pbKeyObject = NULL;
1318 if(cng_init_key(&hAlg, &hKey, &pbKeyObject, key)) {
1319 return NULL;
1320 }
1321
1322 int inlen;
1323 unsigned char *buf = (unsigned char*)util_base64decode_len(in, &inlen);
1324 if(inlen < 16 || !buf) {
1325 cng_cleanup(hAlg, hKey, NULL, pbKeyObject);
1326 if(buf) {
1327 free(buf);
1328 }
1329 return NULL;
1330 }
1331
1332 // encrypted data starts with IV
1333 char iv[16];
1334 memcpy(iv, buf, 16);
1335
1336 // decrypt data
1337 char *data = buf + 16; // encrypted data starts after IV
1338 size_t datalen = inlen - 16;
1339
1340 // create output buffer
1341 ULONG outlen = inlen;
1342 char *out = malloc(outlen + 1);
1343
1344 // decrypt
1345 if(BCryptDecrypt(hKey, data, datalen, NULL, iv, 16, out, outlen, &outlen, BCRYPT_BLOCK_PADDING)) {
1346 cng_cleanup(hAlg, hKey, NULL, pbKeyObject);
1347 free(out);
1348 free(buf);
1349 return NULL;
1350 }
1351
1352 // decrypt finished, return
1353 out[outlen] = 0;
1354 *len = (size_t)outlen;
1355 return out;
1356 }
1357
1358 void dav_get_hash(DAV_SHA_CTX *sha256, unsigned char *buf) {
1359 BCryptFinishHash(sha256->hHash, buf, DAV_SHA256_DIGEST_LENGTH, 0);
1360 }
1361
1362
1363 char* dav_create_hash(const char *data, size_t len) {
1364 unsigned char hash[DAV_SHA256_DIGEST_LENGTH];
1365 DAV_SHA_CTX *ctx = dav_hash_init();
1366 if(ctx) {
1367 dav_hash_update(ctx, data, len);
1368 dav_hash_final(ctx, hash);
1369 }
1370 return util_hexstr(hash, DAV_SHA256_DIGEST_LENGTH);
1371 }
1372
1373 DAV_SHA_CTX* dav_hash_init(void) {
1374 DAV_SHA_CTX *ctx = malloc(sizeof(DAV_SHA_CTX));
1375 if(!ctx) {
1376 return NULL;
1377 }
1378 if(cng_hash_init(ctx)) {
1379 free(ctx);
1380 return NULL;
1381 }
1382 return ctx;
1383 }
1384
1385 void dav_hash_update(DAV_SHA_CTX *ctx, const char *data, size_t len) {
1386 BCryptHashData(ctx->hHash, (PUCHAR)data, len, 0);
1387 }
1388
1389 void dav_hash_final(DAV_SHA_CTX *ctx, unsigned char *buf) {
1390 BCryptFinishHash(ctx->hHash, (PUCHAR)buf, DAV_SHA256_DIGEST_LENGTH, 0);
1391
1392 // cleanup
1393 cng_cleanup(ctx->hAlg, NULL, ctx->hHash, ctx->pbHashObject);
1394 free(ctx);
1395 }
1396
1397 DavKey* dav_pw2key(const char *password, const unsigned char *salt, int saltlen, int pwfunc, int enc) {
1398 if(!password) {
1399 return NULL;
1400 }
1401 size_t len = strlen(password);
1402 if(len == 0) {
1403 return NULL;
1404 }
1405
1406 // setup key data and length
1407 unsigned char keydata[128];
1408 int keylen = 32;
1409 switch(enc) {
1410 case DAV_KEY_AES128: keylen = 16; break;
1411 case DAV_KEY_AES256: keylen = 32; break;
1412 default: return NULL;
1413 }
1414
1415 LPCWSTR algid;
1416 switch(pwfunc) {
1417 case DAV_PWFUNC_PBKDF2_SHA256: algid = BCRYPT_SHA256_ALGORITHM; break;
1418 case DAV_PWFUNC_PBKDF2_SHA512: algid = BCRYPT_SHA512_ALGORITHM; break;
1419 default: return NULL;
1420 }
1421
1422 // open algorithm provider
1423 BCRYPT_ALG_HANDLE hAlg;
1424 ULONG status = BCryptOpenAlgorithmProvider(&hAlg, algid, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG);
1425 if(status > 0) {
1426 fprintf(stderr, "Error: dav_pw2key: BCryptOpenAlgorithmProvider failed: 0x%X\n", (unsigned int)status);
1427 return NULL;
1428 }
1429
1430 // derive key
1431 status = BCryptDeriveKeyPBKDF2(
1432 hAlg,
1433 (PUCHAR)password,
1434 len,
1435 (PUCHAR)salt,
1436 saltlen,
1437 DAV_CRYPTO_ITERATION_COUNT,
1438 keydata,
1439 128,
1440 0);
1441
1442 BCryptCloseAlgorithmProvider(hAlg,0);
1443
1444 if(status) {
1445 fprintf(stderr, "Error: dav_pw2key: BCryptDeriveKeyPBKDF2 failed: 0x%X\n", (unsigned int)status);
1446 return NULL;
1447 }
1448
1449 // create DavKey with generated data
1450 DavKey *key = malloc(sizeof(DavKey));
1451 key->data = malloc(keylen);
1452 key->length = keylen;
1453 key->name = NULL;
1454 key->type = enc;
1455 memcpy(key->data, keydata, keylen);
1456 return key;
1457 }
1458 #endif
1459
1460
1461
894 UcxBuffer* aes_encrypt_buffer(UcxBuffer *in, DavKey *key) { 1462 UcxBuffer* aes_encrypt_buffer(UcxBuffer *in, DavKey *key) {
895 UcxBuffer *encbuf = ucx_buffer_new( 1463 UcxBuffer *encbuf = ucx_buffer_new(
896 NULL, 1464 NULL,
897 in->size+16, 1465 in->size+16,
898 UCX_BUFFER_AUTOEXTEND); 1466 UCX_BUFFER_AUTOEXTEND);

mercurial