Comparison

util-src/crypto.c @ 12735:445f7bd6ffc4

util.crypto, util.jwt: Generate consistent signature sizes (via padding) This fixes the signature parsing and building to work correctly. Sometimes a signature was one or two bytes too short, and needed to be padded. OpenSSL can do this for us.
author Matthew Wild <mwild1@gmail.com>
date Thu, 29 Sep 2022 23:15:39 +0100
parent 12715:5dd00f806e32
child 12837:d3ae47d8a7a7
comparison
equal deleted inserted replaced
12734:447aef5e942c 12735:445f7bd6ffc4
30 #include <openssl/pem.h> 30 #include <openssl/pem.h>
31 31
32 #if (LUA_VERSION_NUM == 501) 32 #if (LUA_VERSION_NUM == 501)
33 #define luaL_setfuncs(L, R, N) luaL_register(L, NULL, R) 33 #define luaL_setfuncs(L, R, N) luaL_register(L, NULL, R)
34 #endif 34 #endif
35
36 /* The max size of an encoded 'R' or 'S' value. P-521 = 521 bits = 66 bytes */
37 #define MAX_ECDSA_SIG_INT_BYTES 66
35 38
36 #include "managed_pointer.h" 39 #include "managed_pointer.h"
37 40
38 #define PKEY_MT_TAG "util.crypto key" 41 #define PKEY_MT_TAG "util.crypto key"
39 42
431 /* r, s = parse_ecdsa_sig(sig_der) */ 434 /* r, s = parse_ecdsa_sig(sig_der) */
432 static int Lparse_ecdsa_signature(lua_State *L) { 435 static int Lparse_ecdsa_signature(lua_State *L) {
433 ECDSA_SIG *sig; 436 ECDSA_SIG *sig;
434 size_t sig_der_len; 437 size_t sig_der_len;
435 const unsigned char *sig_der = (unsigned char*)luaL_checklstring(L, 1, &sig_der_len); 438 const unsigned char *sig_der = (unsigned char*)luaL_checklstring(L, 1, &sig_der_len);
439 const size_t sig_int_bytes = luaL_checkinteger(L, 2);
436 const BIGNUM *r, *s; 440 const BIGNUM *r, *s;
437 unsigned char rb[32];
438 unsigned char sb[32];
439 int rlen, slen; 441 int rlen, slen;
442 unsigned char rb[MAX_ECDSA_SIG_INT_BYTES];
443 unsigned char sb[MAX_ECDSA_SIG_INT_BYTES];
444
445 if(sig_int_bytes > MAX_ECDSA_SIG_INT_BYTES) {
446 luaL_error(L, "requested signature size exceeds supported limit");
447 }
440 448
441 sig = d2i_ECDSA_SIG(NULL, &sig_der, sig_der_len); 449 sig = d2i_ECDSA_SIG(NULL, &sig_der, sig_der_len);
442 450
443 if(sig == NULL) { 451 if(sig == NULL) {
444 lua_pushnil(L); 452 lua_pushnil(L);
445 return 1; 453 return 1;
446 } 454 }
447 455
448 ECDSA_SIG_get0(sig, &r, &s); 456 ECDSA_SIG_get0(sig, &r, &s);
449 457
450 rlen = BN_num_bytes(r); 458 rlen = BN_bn2binpad(r, rb, sig_int_bytes);
451 slen = BN_num_bytes(s); 459 slen = BN_bn2binpad(s, sb, sig_int_bytes);
452 460
453 if (rlen > 32 || slen > 32) { 461 if (rlen == -1 || slen == -1) {
454 ECDSA_SIG_free(sig); 462 ECDSA_SIG_free(sig);
455 luaL_error(L, "unexpectedly large signature integers"); 463 luaL_error(L, "encoded integers exceed requested size");
456 } 464 }
457
458 BN_bn2bin(r, rb);
459 BN_bn2bin(s, sb);
460 465
461 ECDSA_SIG_free(sig); 466 ECDSA_SIG_free(sig);
462 467
463 lua_pushlstring(L, (const char*)rb, rlen); 468 lua_pushlstring(L, (const char*)rb, rlen);
464 lua_pushlstring(L, (const char*)sb, slen); 469 lua_pushlstring(L, (const char*)sb, slen);
483 488
484 ECDSA_SIG_set0(sig, r, s); 489 ECDSA_SIG_set0(sig, r, s);
485 490
486 luaL_buffinit(L, &sigbuf); 491 luaL_buffinit(L, &sigbuf);
487 492
488 unsigned char *buffer = (unsigned char*)luaL_prepbuffsize(&sigbuf, rlen+slen+32); 493 /* DER structure of an ECDSA signature has 7 bytes plus the integers themselves,
494 which may gain an extra byte once encoded */
495 unsigned char *buffer = (unsigned char*)luaL_prepbuffsize(&sigbuf, (rlen+1)+(slen+1)+7);
489 int len = i2d_ECDSA_SIG(sig, &buffer); 496 int len = i2d_ECDSA_SIG(sig, &buffer);
490 luaL_addsize(&sigbuf, len); 497 luaL_addsize(&sigbuf, len);
491 luaL_pushresult(&sigbuf); 498 luaL_pushresult(&sigbuf);
492 499
493 ECDSA_SIG_free(sig); 500 ECDSA_SIG_free(sig);