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); |