Software /
code /
prosody
Comparison
util-src/crypto.c @ 12837:d3ae47d8a7a7
util.crypto: Add support for AES-256-CTR
This is required by PASETO v3.local
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Fri, 13 Jan 2023 14:34:10 +0000 |
parent | 12735:445f7bd6ffc4 |
child | 12876:0ed24f48b6a6 |
comparison
equal
deleted
inserted
replaced
12836:dbe9781fd278 | 12837:d3ae47d8a7a7 |
---|---|
283 | 283 |
284 static int Led25519_verify(lua_State *L) { | 284 static int Led25519_verify(lua_State *L) { |
285 return base_evp_verify(L, NID_ED25519, NULL); | 285 return base_evp_verify(L, NID_ED25519, NULL); |
286 } | 286 } |
287 | 287 |
288 /* gcm_encrypt(key, iv, plaintext) */ | 288 /* encrypt(key, iv, plaintext) */ |
289 static int Laes_gcm_encrypt(lua_State *L, const EVP_CIPHER *cipher, const unsigned char expected_key_len) { | 289 static int Levp_encrypt(lua_State *L, const EVP_CIPHER *cipher, const unsigned char expected_key_len, const unsigned char expected_iv_len, const size_t tag_len) { |
290 EVP_CIPHER_CTX *ctx; | 290 EVP_CIPHER_CTX *ctx; |
291 luaL_Buffer ciphertext_buffer; | 291 luaL_Buffer ciphertext_buffer; |
292 | 292 |
293 size_t key_len, iv_len, plaintext_len; | 293 size_t key_len, iv_len, plaintext_len; |
294 int ciphertext_len, final_len; | 294 int ciphertext_len, final_len; |
298 const unsigned char *plaintext = (unsigned char*)luaL_checklstring(L, 3, &plaintext_len); | 298 const unsigned char *plaintext = (unsigned char*)luaL_checklstring(L, 3, &plaintext_len); |
299 | 299 |
300 if(key_len != expected_key_len) { | 300 if(key_len != expected_key_len) { |
301 return luaL_error(L, "key must be %d bytes", expected_key_len); | 301 return luaL_error(L, "key must be %d bytes", expected_key_len); |
302 } | 302 } |
303 luaL_argcheck(L, iv_len == 12, 2, "iv must be 12 bytes"); | 303 if(iv_len != expected_iv_len) { |
304 return luaL_error(L, "iv must be %d bytes", expected_iv_len); | |
305 } | |
304 if(lua_gettop(L) > 3) { | 306 if(lua_gettop(L) > 3) { |
305 return luaL_error(L, "Expected 3 arguments, got %d", lua_gettop(L)); | 307 return luaL_error(L, "Expected 3 arguments, got %d", lua_gettop(L)); |
306 } | 308 } |
307 | 309 |
308 // Create and initialise the context | 310 // Create and initialise the context |
317 if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) { | 319 if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) { |
318 return luaL_error(L, "Error while initializing key/iv"); | 320 return luaL_error(L, "Error while initializing key/iv"); |
319 } | 321 } |
320 | 322 |
321 luaL_buffinit(L, &ciphertext_buffer); | 323 luaL_buffinit(L, &ciphertext_buffer); |
322 unsigned char *ciphertext = (unsigned char*)luaL_prepbuffsize(&ciphertext_buffer, plaintext_len+16); | 324 unsigned char *ciphertext = (unsigned char*)luaL_prepbuffsize(&ciphertext_buffer, plaintext_len+tag_len); |
323 | 325 |
324 if(1 != EVP_EncryptUpdate(ctx, ciphertext, &ciphertext_len, plaintext, plaintext_len)) { | 326 if(1 != EVP_EncryptUpdate(ctx, ciphertext, &ciphertext_len, plaintext, plaintext_len)) { |
325 return luaL_error(L, "Error while encrypting data"); | 327 return luaL_error(L, "Error while encrypting data"); |
326 } | 328 } |
327 | 329 |
334 } | 336 } |
335 if(final_len != 0) { | 337 if(final_len != 0) { |
336 return luaL_error(L, "Non-zero final data"); | 338 return luaL_error(L, "Non-zero final data"); |
337 } | 339 } |
338 | 340 |
339 /* Get the tag */ | 341 if(tag_len > 0) { |
340 if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, ciphertext + ciphertext_len)) { | 342 /* Get the tag */ |
341 return luaL_error(L, "Unable to read AEAD tag of encrypted data"); | 343 if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, tag_len, ciphertext + ciphertext_len)) { |
342 } | 344 return luaL_error(L, "Unable to read AEAD tag of encrypted data"); |
343 | 345 } |
344 luaL_addsize(&ciphertext_buffer, ciphertext_len + 16); | 346 /* Append tag */ |
347 luaL_addsize(&ciphertext_buffer, ciphertext_len + tag_len); | |
348 } else { | |
349 luaL_addsize(&ciphertext_buffer, ciphertext_len); | |
350 } | |
345 luaL_pushresult(&ciphertext_buffer); | 351 luaL_pushresult(&ciphertext_buffer); |
346 | 352 |
347 return 1; | 353 return 1; |
348 } | 354 } |
349 | 355 |
350 static int Laes_128_gcm_encrypt(lua_State *L) { | 356 static int Laes_128_gcm_encrypt(lua_State *L) { |
351 return Laes_gcm_encrypt(L, EVP_aes_128_gcm(), 16); | 357 return Levp_encrypt(L, EVP_aes_128_gcm(), 16, 12, 16); |
352 } | 358 } |
353 | 359 |
354 static int Laes_256_gcm_encrypt(lua_State *L) { | 360 static int Laes_256_gcm_encrypt(lua_State *L) { |
355 return Laes_gcm_encrypt(L, EVP_aes_256_gcm(), 32); | 361 return Levp_encrypt(L, EVP_aes_256_gcm(), 32, 12, 16); |
356 } | 362 } |
357 | 363 |
358 /* gcm_decrypt(key, iv, ciphertext) */ | 364 static int Laes_256_ctr_encrypt(lua_State *L) { |
359 static int Laes_gcm_decrypt(lua_State *L, const EVP_CIPHER *cipher, const unsigned char expected_key_len) { | 365 return Levp_encrypt(L, EVP_aes_256_ctr(), 32, 16, 0); |
366 } | |
367 | |
368 /* decrypt(key, iv, ciphertext) */ | |
369 static int Levp_decrypt(lua_State *L, const EVP_CIPHER *cipher, const unsigned char expected_key_len, const unsigned char expected_iv_len, const size_t tag_len) { | |
360 EVP_CIPHER_CTX *ctx; | 370 EVP_CIPHER_CTX *ctx; |
361 luaL_Buffer plaintext_buffer; | 371 luaL_Buffer plaintext_buffer; |
362 | 372 |
363 size_t key_len, iv_len, ciphertext_len; | 373 size_t key_len, iv_len, ciphertext_len; |
364 int plaintext_len, final_len; | 374 int plaintext_len, final_len; |
368 const unsigned char *ciphertext = (unsigned char*)luaL_checklstring(L, 3, &ciphertext_len); | 378 const unsigned char *ciphertext = (unsigned char*)luaL_checklstring(L, 3, &ciphertext_len); |
369 | 379 |
370 if(key_len != expected_key_len) { | 380 if(key_len != expected_key_len) { |
371 return luaL_error(L, "key must be %d bytes", expected_key_len); | 381 return luaL_error(L, "key must be %d bytes", expected_key_len); |
372 } | 382 } |
373 luaL_argcheck(L, iv_len == 12, 2, "iv must be 12 bytes"); | 383 if(iv_len != expected_iv_len) { |
374 luaL_argcheck(L, ciphertext_len > 16, 3, "ciphertext must be at least 16 bytes (including tag)"); | 384 return luaL_error(L, "iv must be %d bytes", expected_iv_len); |
385 } | |
386 if(ciphertext_len <= tag_len) { | |
387 return luaL_error(L, "ciphertext must be at least %d bytes (including tag)", tag_len); | |
388 } | |
375 if(lua_gettop(L) > 3) { | 389 if(lua_gettop(L) > 3) { |
376 return luaL_error(L, "Expected 3 arguments, got %d", lua_gettop(L)); | 390 return luaL_error(L, "Expected 3 arguments, got %d", lua_gettop(L)); |
377 } | 391 } |
378 | 392 |
379 /* Create and initialise the context */ | 393 /* Create and initialise the context */ |
394 | 408 |
395 /* | 409 /* |
396 * Provide the message to be decrypted, and obtain the plaintext output. | 410 * Provide the message to be decrypted, and obtain the plaintext output. |
397 * EVP_DecryptUpdate can be called multiple times if necessary | 411 * EVP_DecryptUpdate can be called multiple times if necessary |
398 */ | 412 */ |
399 if(!EVP_DecryptUpdate(ctx, plaintext, &plaintext_len, ciphertext, ciphertext_len-16)) { | 413 if(!EVP_DecryptUpdate(ctx, plaintext, &plaintext_len, ciphertext, ciphertext_len-tag_len)) { |
400 return luaL_error(L, "Error while decrypting data"); | 414 return luaL_error(L, "Error while decrypting data"); |
401 } | 415 } |
402 | 416 |
403 /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ | 417 if(tag_len > 0) { |
404 if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, (unsigned char*)ciphertext + (ciphertext_len-16))) { | 418 /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ |
405 return luaL_error(L, "Error while processing authentication tag"); | 419 if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, (unsigned char*)ciphertext + (ciphertext_len-tag_len))) { |
420 return luaL_error(L, "Error while processing authentication tag"); | |
421 } | |
406 } | 422 } |
407 | 423 |
408 /* | 424 /* |
409 * Finalise the decryption. A positive return value indicates success, | 425 * Finalise the decryption. A positive return value indicates success, |
410 * anything else is a failure - the plaintext is not trustworthy. | 426 * anything else is a failure - the plaintext is not trustworthy. |
422 luaL_pushresult(&plaintext_buffer); | 438 luaL_pushresult(&plaintext_buffer); |
423 return 1; | 439 return 1; |
424 } | 440 } |
425 | 441 |
426 static int Laes_128_gcm_decrypt(lua_State *L) { | 442 static int Laes_128_gcm_decrypt(lua_State *L) { |
427 return Laes_gcm_decrypt(L, EVP_aes_128_gcm(), 16); | 443 return Levp_decrypt(L, EVP_aes_128_gcm(), 16, 12, 16); |
428 } | 444 } |
429 | 445 |
430 static int Laes_256_gcm_decrypt(lua_State *L) { | 446 static int Laes_256_gcm_decrypt(lua_State *L) { |
431 return Laes_gcm_decrypt(L, EVP_aes_256_gcm(), 32); | 447 return Levp_decrypt(L, EVP_aes_256_gcm(), 32, 12, 16); |
448 } | |
449 | |
450 static int Laes_256_ctr_decrypt(lua_State *L) { | |
451 return Levp_decrypt(L, EVP_aes_256_ctr(), 32, 16, 0); | |
432 } | 452 } |
433 | 453 |
434 /* r, s = parse_ecdsa_sig(sig_der) */ | 454 /* r, s = parse_ecdsa_sig(sig_der) */ |
435 static int Lparse_ecdsa_signature(lua_State *L) { | 455 static int Lparse_ecdsa_signature(lua_State *L) { |
436 ECDSA_SIG *sig; | 456 ECDSA_SIG *sig; |
545 { "aes_128_gcm_encrypt", Laes_128_gcm_encrypt }, | 565 { "aes_128_gcm_encrypt", Laes_128_gcm_encrypt }, |
546 { "aes_128_gcm_decrypt", Laes_128_gcm_decrypt }, | 566 { "aes_128_gcm_decrypt", Laes_128_gcm_decrypt }, |
547 { "aes_256_gcm_encrypt", Laes_256_gcm_encrypt }, | 567 { "aes_256_gcm_encrypt", Laes_256_gcm_encrypt }, |
548 { "aes_256_gcm_decrypt", Laes_256_gcm_decrypt }, | 568 { "aes_256_gcm_decrypt", Laes_256_gcm_decrypt }, |
549 | 569 |
570 { "aes_256_ctr_encrypt", Laes_256_ctr_encrypt }, | |
571 { "aes_256_ctr_decrypt", Laes_256_ctr_decrypt }, | |
572 | |
550 { "generate_ed25519_keypair", Lgenerate_ed25519_keypair }, | 573 { "generate_ed25519_keypair", Lgenerate_ed25519_keypair }, |
551 | 574 |
552 { "import_private_pem", Limport_private_pem }, | 575 { "import_private_pem", Limport_private_pem }, |
553 { "import_public_pem", Limport_public_pem }, | 576 { "import_public_pem", Limport_public_pem }, |
554 | 577 |