Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite6bdfd9

Browse files
committed
Refactor HMAC implementations
Similarly to the cryptohash implementations, this refactors the existingHMAC code into a single set of APIs that can be plugged with any cryptolibraries PostgreSQL is built with (only OpenSSL currently). If thereis no such libraries, a fallback implementation is available. Those newAPIs are designed similarly to the existing cryptohash layer, so thereis no real new design here, with the same logic around buffer boundchecks and memory handling.HMAC has a dependency on cryptohashes, so all the cryptohash typessupported by cryptohash{_openssl}.c can be used with HMAC. Thisrefactoring is an advantage mainly for SCRAM, that included its ownimplementation of HMAC with SHA256 without relying on the existingcrypto libraries even if PostgreSQL was built with their support.This code has been tested on Windows and Linux, with and withoutOpenSSL, across all the versions supported on HEAD from 1.1.1 down to1.0.1. I have also checked that the implementations are working fineusing some sample results, a custom extension of my own, and doingcross-checks across different major versions with SCRAM with the clientand the backend.Author: Michael PaquierReviewed-by: Bruce MomjianDiscussion:https://postgr.es/m/X9m0nkEJEzIPXjeZ@paquier.xyz
1 parent1d9c5d0 commite6bdfd9

File tree

18 files changed

+749
-200
lines changed

18 files changed

+749
-200
lines changed

‎configure

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12642,7 +12642,7 @@ done
1264212642
# defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
1264312643
# doesn't have these OpenSSL 1.1.0 functions. So check for individual
1264412644
# functions.
12645-
for ac_func in OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data
12645+
for ac_func in OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free
1264612646
do :
1264712647
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
1264812648
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"

‎configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1258,7 +1258,7 @@ if test "$with_ssl" = openssl ; then
12581258
# defines OPENSSL_VERSION_NUMBER to claim version 2.0.0, even though it
12591259
# doesn't have these OpenSSL 1.1.0 functions. So check for individual
12601260
# functions.
1261-
AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data])
1261+
AC_CHECK_FUNCS([OPENSSL_init_ssl BIO_get_data BIO_meth_new ASN1_STRING_get0_data HMAC_CTX_new HMAC_CTX_free])
12621262
# OpenSSL versions before 1.1.0 required setting callback functions, for
12631263
# thread-safety. In 1.1.0, it's no longer required, and CRYPTO_lock()
12641264
# function was removed.

‎src/backend/libpq/auth-scram.c

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
#include"catalog/pg_authid.h"
9696
#include"catalog/pg_control.h"
9797
#include"common/base64.h"
98+
#include"common/hmac.h"
9899
#include"common/saslprep.h"
99100
#include"common/scram-common.h"
100101
#include"common/sha2.h"
@@ -1100,31 +1101,33 @@ verify_client_proof(scram_state *state)
11001101
uint8ClientSignature[SCRAM_KEY_LEN];
11011102
uint8ClientKey[SCRAM_KEY_LEN];
11021103
uint8client_StoredKey[SCRAM_KEY_LEN];
1103-
scram_HMAC_ctxctx;
1104+
pg_hmac_ctx*ctx=pg_hmac_create(PG_SHA256);
11041105
inti;
11051106

11061107
/*
11071108
* Calculate ClientSignature. Note that we don't log directly a failure
11081109
* here even when processing the calculations as this could involve a mock
11091110
* authentication.
11101111
*/
1111-
if (scram_HMAC_init(&ctx,state->StoredKey,SCRAM_KEY_LEN)<0||
1112-
scram_HMAC_update(&ctx,
1113-
state->client_first_message_bare,
1114-
strlen(state->client_first_message_bare))<0||
1115-
scram_HMAC_update(&ctx,",",1)<0||
1116-
scram_HMAC_update(&ctx,
1117-
state->server_first_message,
1118-
strlen(state->server_first_message))<0||
1119-
scram_HMAC_update(&ctx,",",1)<0||
1120-
scram_HMAC_update(&ctx,
1121-
state->client_final_message_without_proof,
1122-
strlen(state->client_final_message_without_proof))<0||
1123-
scram_HMAC_final(ClientSignature,&ctx)<0)
1112+
if (pg_hmac_init(ctx,state->StoredKey,SCRAM_KEY_LEN)<0||
1113+
pg_hmac_update(ctx,
1114+
(uint8*)state->client_first_message_bare,
1115+
strlen(state->client_first_message_bare))<0||
1116+
pg_hmac_update(ctx, (uint8*)",",1)<0||
1117+
pg_hmac_update(ctx,
1118+
(uint8*)state->server_first_message,
1119+
strlen(state->server_first_message))<0||
1120+
pg_hmac_update(ctx, (uint8*)",",1)<0||
1121+
pg_hmac_update(ctx,
1122+
(uint8*)state->client_final_message_without_proof,
1123+
strlen(state->client_final_message_without_proof))<0||
1124+
pg_hmac_final(ctx,ClientSignature,sizeof(ClientSignature))<0)
11241125
{
11251126
elog(ERROR,"could not calculate client signature");
11261127
}
11271128

1129+
pg_hmac_free(ctx);
1130+
11281131
/* Extract the ClientKey that the client calculated from the proof */
11291132
for (i=0;i<SCRAM_KEY_LEN;i++)
11301133
ClientKey[i]=state->ClientProof[i] ^ClientSignature[i];
@@ -1359,26 +1362,28 @@ build_server_final_message(scram_state *state)
13591362
uint8ServerSignature[SCRAM_KEY_LEN];
13601363
char*server_signature_base64;
13611364
intsiglen;
1362-
scram_HMAC_ctxctx;
1365+
pg_hmac_ctx*ctx=pg_hmac_create(PG_SHA256);
13631366

13641367
/* calculate ServerSignature */
1365-
if (scram_HMAC_init(&ctx,state->ServerKey,SCRAM_KEY_LEN)<0||
1366-
scram_HMAC_update(&ctx,
1367-
state->client_first_message_bare,
1368-
strlen(state->client_first_message_bare))<0||
1369-
scram_HMAC_update(&ctx,",",1)<0||
1370-
scram_HMAC_update(&ctx,
1371-
state->server_first_message,
1372-
strlen(state->server_first_message))<0||
1373-
scram_HMAC_update(&ctx,",",1)<0||
1374-
scram_HMAC_update(&ctx,
1375-
state->client_final_message_without_proof,
1376-
strlen(state->client_final_message_without_proof))<0||
1377-
scram_HMAC_final(ServerSignature,&ctx)<0)
1368+
if (pg_hmac_init(ctx,state->ServerKey,SCRAM_KEY_LEN)<0||
1369+
pg_hmac_update(ctx,
1370+
(uint8*)state->client_first_message_bare,
1371+
strlen(state->client_first_message_bare))<0||
1372+
pg_hmac_update(ctx, (uint8*)",",1)<0||
1373+
pg_hmac_update(ctx,
1374+
(uint8*)state->server_first_message,
1375+
strlen(state->server_first_message))<0||
1376+
pg_hmac_update(ctx, (uint8*)",",1)<0||
1377+
pg_hmac_update(ctx,
1378+
(uint8*)state->client_final_message_without_proof,
1379+
strlen(state->client_final_message_without_proof))<0||
1380+
pg_hmac_final(ctx,ServerSignature,sizeof(ServerSignature))<0)
13781381
{
13791382
elog(ERROR,"could not calculate server signature");
13801383
}
13811384

1385+
pg_hmac_free(ctx);
1386+
13821387
siglen=pg_b64_enc_len(SCRAM_KEY_LEN);
13831388
/* don't forget the zero-terminator */
13841389
server_signature_base64=palloc(siglen+1);

‎src/backend/utils/resowner/resowner.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include"common/cryptohash.h"
2424
#include"common/hashfn.h"
25+
#include"common/hmac.h"
2526
#include"jit/jit.h"
2627
#include"storage/bufmgr.h"
2728
#include"storage/ipc.h"
@@ -130,6 +131,7 @@ typedef struct ResourceOwnerData
130131
ResourceArraydsmarr;/* dynamic shmem segments */
131132
ResourceArrayjitarr;/* JIT contexts */
132133
ResourceArraycryptohasharr;/* cryptohash contexts */
134+
ResourceArrayhmacarr;/* HMAC contexts */
133135

134136
/* We can remember up to MAX_RESOWNER_LOCKS references to local locks. */
135137
intnlocks;/* number of owned locks */
@@ -178,6 +180,7 @@ static void PrintSnapshotLeakWarning(Snapshot snapshot);
178180
staticvoidPrintFileLeakWarning(Filefile);
179181
staticvoidPrintDSMLeakWarning(dsm_segment*seg);
180182
staticvoidPrintCryptoHashLeakWarning(Datumhandle);
183+
staticvoidPrintHMACLeakWarning(Datumhandle);
181184

182185

183186
/*****************************************************************************
@@ -448,6 +451,7 @@ ResourceOwnerCreate(ResourceOwner parent, const char *name)
448451
ResourceArrayInit(&(owner->dsmarr),PointerGetDatum(NULL));
449452
ResourceArrayInit(&(owner->jitarr),PointerGetDatum(NULL));
450453
ResourceArrayInit(&(owner->cryptohasharr),PointerGetDatum(NULL));
454+
ResourceArrayInit(&(owner->hmacarr),PointerGetDatum(NULL));
451455

452456
returnowner;
453457
}
@@ -568,6 +572,16 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
568572
PrintCryptoHashLeakWarning(foundres);
569573
pg_cryptohash_free(context);
570574
}
575+
576+
/* Ditto for HMAC contexts */
577+
while (ResourceArrayGetAny(&(owner->hmacarr),&foundres))
578+
{
579+
pg_hmac_ctx*context= (pg_hmac_ctx*)PointerGetDatum(foundres);
580+
581+
if (isCommit)
582+
PrintHMACLeakWarning(foundres);
583+
pg_hmac_free(context);
584+
}
571585
}
572586
elseif (phase==RESOURCE_RELEASE_LOCKS)
573587
{
@@ -737,6 +751,7 @@ ResourceOwnerDelete(ResourceOwner owner)
737751
Assert(owner->dsmarr.nitems==0);
738752
Assert(owner->jitarr.nitems==0);
739753
Assert(owner->cryptohasharr.nitems==0);
754+
Assert(owner->hmacarr.nitems==0);
740755
Assert(owner->nlocks==0||owner->nlocks==MAX_RESOWNER_LOCKS+1);
741756

742757
/*
@@ -765,6 +780,7 @@ ResourceOwnerDelete(ResourceOwner owner)
765780
ResourceArrayFree(&(owner->dsmarr));
766781
ResourceArrayFree(&(owner->jitarr));
767782
ResourceArrayFree(&(owner->cryptohasharr));
783+
ResourceArrayFree(&(owner->hmacarr));
768784

769785
pfree(owner);
770786
}
@@ -1428,3 +1444,48 @@ PrintCryptoHashLeakWarning(Datum handle)
14281444
elog(WARNING,"cryptohash context reference leak: context %p still referenced",
14291445
DatumGetPointer(handle));
14301446
}
1447+
1448+
/*
1449+
* Make sure there is room for at least one more entry in a ResourceOwner's
1450+
* hmac context reference array.
1451+
*
1452+
* This is separate from actually inserting an entry because if we run out of
1453+
* memory, it's critical to do so *before* acquiring the resource.
1454+
*/
1455+
void
1456+
ResourceOwnerEnlargeHMAC(ResourceOwnerowner)
1457+
{
1458+
ResourceArrayEnlarge(&(owner->hmacarr));
1459+
}
1460+
1461+
/*
1462+
* Remember that a HMAC context is owned by a ResourceOwner
1463+
*
1464+
* Caller must have previously done ResourceOwnerEnlargeHMAC()
1465+
*/
1466+
void
1467+
ResourceOwnerRememberHMAC(ResourceOwnerowner,Datumhandle)
1468+
{
1469+
ResourceArrayAdd(&(owner->hmacarr),handle);
1470+
}
1471+
1472+
/*
1473+
* Forget that a HMAC context is owned by a ResourceOwner
1474+
*/
1475+
void
1476+
ResourceOwnerForgetHMAC(ResourceOwnerowner,Datumhandle)
1477+
{
1478+
if (!ResourceArrayRemove(&(owner->hmacarr),handle))
1479+
elog(ERROR,"HMAC context %p is not owned by resource owner %s",
1480+
DatumGetPointer(handle),owner->name);
1481+
}
1482+
1483+
/*
1484+
* Debugging subroutine
1485+
*/
1486+
staticvoid
1487+
PrintHMACLeakWarning(Datumhandle)
1488+
{
1489+
elog(WARNING,"HMAC context reference leak: context %p still referenced",
1490+
DatumGetPointer(handle));
1491+
}

‎src/common/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,12 @@ OBJS_COMMON = \
8383
ifeq ($(with_ssl),openssl)
8484
OBJS_COMMON +=\
8585
protocol_openssl.o\
86-
cryptohash_openssl.o
86+
cryptohash_openssl.o\
87+
hmac_openssl.o
8788
else
8889
OBJS_COMMON +=\
8990
cryptohash.o\
91+
hmac.o\
9092
md5.o\
9193
sha1.o\
9294
sha2.o

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp