Software /
code /
prosody
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); |