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

Commitd981074

Browse files
committed
Misc SCRAM code cleanups.
* Move computation of SaltedPassword to a separate function from scram_ClientOrServerKey(). This saves a lot of cycles in libpq, by computing SaltedPassword only once per authentication. (Computing SaltedPassword is expensive by design.)* Split scram_ClientOrServerKey() into two functions. Improves readability, by making the calling code less verbose.* Rename "server proof" to "server signature", to better match the nomenclature used in RFC 5802.* Rename SCRAM_SALT_LEN to SCRAM_DEFAULT_SALT_LEN, to make it more clear that the salt can be of any length, and the constant only specifies how long a salt we use when we generate a new verifier. Also rename SCRAM_ITERATIONS_DEFAULT to SCRAM_DEFAULT_ITERATIONS, for consistency.These things caught my eye while working on other upcoming changes.
1 parentb9a3ef5 commitd981074

File tree

4 files changed

+89
-71
lines changed

4 files changed

+89
-71
lines changed

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

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,8 @@ scram_build_verifier(const char *username, const char *password,
396396
{
397397
char*prep_password=NULL;
398398
pg_saslprep_rcrc;
399-
charsaltbuf[SCRAM_SALT_LEN];
399+
charsaltbuf[SCRAM_DEFAULT_SALT_LEN];
400+
uint8salted_password[SCRAM_KEY_LEN];
400401
uint8keybuf[SCRAM_KEY_LEN];
401402
char*encoded_salt;
402403
char*encoded_storedkey;
@@ -414,24 +415,25 @@ scram_build_verifier(const char *username, const char *password,
414415
password= (constchar*)prep_password;
415416

416417
if (iterations <=0)
417-
iterations=SCRAM_ITERATIONS_DEFAULT;
418+
iterations=SCRAM_DEFAULT_ITERATIONS;
418419

419420
/* Generate salt, and encode it in base64 */
420-
if (!pg_backend_random(saltbuf,SCRAM_SALT_LEN))
421+
if (!pg_backend_random(saltbuf,SCRAM_DEFAULT_SALT_LEN))
421422
{
422423
ereport(LOG,
423424
(errcode(ERRCODE_INTERNAL_ERROR),
424425
errmsg("could not generate random salt")));
425426
returnNULL;
426427
}
427428

428-
encoded_salt=palloc(pg_b64_enc_len(SCRAM_SALT_LEN)+1);
429-
encoded_len=pg_b64_encode(saltbuf,SCRAM_SALT_LEN,encoded_salt);
429+
encoded_salt=palloc(pg_b64_enc_len(SCRAM_DEFAULT_SALT_LEN)+1);
430+
encoded_len=pg_b64_encode(saltbuf,SCRAM_DEFAULT_SALT_LEN,encoded_salt);
430431
encoded_salt[encoded_len]='\0';
431432

432433
/* Calculate StoredKey, and encode it in base64 */
433-
scram_ClientOrServerKey(password,saltbuf,SCRAM_SALT_LEN,
434-
iterations,SCRAM_CLIENT_KEY_NAME,keybuf);
434+
scram_SaltedPassword(password,saltbuf,SCRAM_DEFAULT_SALT_LEN,
435+
iterations,salted_password);
436+
scram_ClientKey(salted_password,keybuf);
435437
scram_H(keybuf,SCRAM_KEY_LEN,keybuf);/* StoredKey */
436438

437439
encoded_storedkey=palloc(pg_b64_enc_len(SCRAM_KEY_LEN)+1);
@@ -440,8 +442,7 @@ scram_build_verifier(const char *username, const char *password,
440442
encoded_storedkey[encoded_len]='\0';
441443

442444
/* And same for ServerKey */
443-
scram_ClientOrServerKey(password,saltbuf,SCRAM_SALT_LEN,iterations,
444-
SCRAM_SERVER_KEY_NAME,keybuf);
445+
scram_ServerKey(salted_password,keybuf);
445446

446447
encoded_serverkey=palloc(pg_b64_enc_len(SCRAM_KEY_LEN)+1);
447448
encoded_len=pg_b64_encode((constchar*)keybuf,SCRAM_KEY_LEN,
@@ -473,6 +474,7 @@ scram_verify_plain_password(const char *username, const char *password,
473474
char*salt;
474475
intsaltlen;
475476
intiterations;
477+
uint8salted_password[SCRAM_KEY_LEN];
476478
uint8stored_key[SCRAM_KEY_LEN];
477479
uint8server_key[SCRAM_KEY_LEN];
478480
uint8computed_key[SCRAM_KEY_LEN];
@@ -502,9 +504,9 @@ scram_verify_plain_password(const char *username, const char *password,
502504
if (rc==SASLPREP_SUCCESS)
503505
password=prep_password;
504506

505-
/* Compute Serverkey based on the user-supplied plaintext password */
506-
scram_ClientOrServerKey(password,salt,saltlen,iterations,
507-
SCRAM_SERVER_KEY_NAME,computed_key);
507+
/* Compute ServerKey based on the user-supplied plaintext password */
508+
scram_SaltedPassword(password,salt,saltlen,iterations,salted_password);
509+
scram_ServerKey(salted_password,computed_key);
508510

509511
if (prep_password)
510512
pfree(prep_password);
@@ -630,12 +632,12 @@ mock_scram_verifier(const char *username, int *iterations, char **salt,
630632
/* Generate deterministic salt */
631633
raw_salt=scram_MockSalt(username);
632634

633-
encoded_salt= (char*)palloc(pg_b64_enc_len(SCRAM_SALT_LEN)+1);
634-
encoded_len=pg_b64_encode(raw_salt,SCRAM_SALT_LEN,encoded_salt);
635+
encoded_salt= (char*)palloc(pg_b64_enc_len(SCRAM_DEFAULT_SALT_LEN)+1);
636+
encoded_len=pg_b64_encode(raw_salt,SCRAM_DEFAULT_SALT_LEN,encoded_salt);
635637
encoded_salt[encoded_len]='\0';
636638

637639
*salt=encoded_salt;
638-
*iterations=SCRAM_ITERATIONS_DEFAULT;
640+
*iterations=SCRAM_DEFAULT_ITERATIONS;
639641

640642
/* StoredKey and ServerKey are not used in a doomed authentication */
641643
memset(stored_key,0,SCRAM_KEY_LEN);
@@ -1179,7 +1181,7 @@ build_server_final_message(scram_state *state)
11791181
/*
11801182
* Determinisitcally generate salt for mock authentication, using a SHA256
11811183
* hash based on the username and a cluster-level secret key. Returns a
1182-
* pointer to a static buffer of sizeSCRAM_SALT_LEN.
1184+
* pointer to a static buffer of sizeSCRAM_DEFAULT_SALT_LEN.
11831185
*/
11841186
staticchar*
11851187
scram_MockSalt(constchar*username)
@@ -1194,7 +1196,7 @@ scram_MockSalt(const char *username)
11941196
* not larger the SHA256 digest length. If the salt is smaller, the caller
11951197
* will just ignore the extra data))
11961198
*/
1197-
StaticAssertStmt(PG_SHA256_DIGEST_LENGTH >=SCRAM_SALT_LEN,
1199+
StaticAssertStmt(PG_SHA256_DIGEST_LENGTH >=SCRAM_DEFAULT_SALT_LEN,
11981200
"salt length greater than SHA256 digest length");
11991201

12001202
pg_sha256_init(&ctx);

‎src/common/scram-common.c

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -98,23 +98,31 @@ scram_HMAC_final(uint8 *result, scram_HMAC_ctx *ctx)
9898
}
9999

100100
/*
101-
*Iterate hash calculation of HMAC entry using given salt.
102-
* scram_Hi() is essentially PBKDF2 (see RFC2898) with HMAC() as the
103-
*pseudorandom function.
101+
*Calculate SaltedPassword.
102+
*
103+
*The password should already be normalized by SASLprep.
104104
*/
105-
staticvoid
106-
scram_Hi(constchar*str,constchar*salt,intsaltlen,intiterations,uint8*result)
105+
void
106+
scram_SaltedPassword(constchar*password,
107+
constchar*salt,intsaltlen,intiterations,
108+
uint8*result)
107109
{
108-
intstr_len=strlen(str);
110+
intpassword_len=strlen(password);
109111
uint32one=htonl(1);
110112
inti,
111113
j;
112114
uint8Ui[SCRAM_KEY_LEN];
113115
uint8Ui_prev[SCRAM_KEY_LEN];
114116
scram_HMAC_ctxhmac_ctx;
115117

118+
/*
119+
* Iterate hash calculation of HMAC entry using given salt. This is
120+
* essentially PBKDF2 (see RFC2898) with HMAC() as the pseudorandom
121+
* function.
122+
*/
123+
116124
/* First iteration */
117-
scram_HMAC_init(&hmac_ctx, (uint8*)str,str_len);
125+
scram_HMAC_init(&hmac_ctx, (uint8*)password,password_len);
118126
scram_HMAC_update(&hmac_ctx,salt,saltlen);
119127
scram_HMAC_update(&hmac_ctx, (char*)&one,sizeof(uint32));
120128
scram_HMAC_final(Ui_prev,&hmac_ctx);
@@ -123,7 +131,7 @@ scram_Hi(const char *str, const char *salt, int saltlen, int iterations, uint8 *
123131
/* Subsequent iterations */
124132
for (i=2;i <=iterations;i++)
125133
{
126-
scram_HMAC_init(&hmac_ctx, (uint8*)str,str_len);
134+
scram_HMAC_init(&hmac_ctx, (uint8*)password,password_len);
127135
scram_HMAC_update(&hmac_ctx, (constchar*)Ui_prev,SCRAM_KEY_LEN);
128136
scram_HMAC_final(Ui,&hmac_ctx);
129137
for (j=0;j<SCRAM_KEY_LEN;j++)
@@ -148,20 +156,27 @@ scram_H(const uint8 *input, int len, uint8 *result)
148156
}
149157

150158
/*
151-
* Calculate ClientKey or ServerKey.
152-
*
153-
* The password should already be normalized by SASLprep.
159+
* Calculate ClientKey.
154160
*/
155161
void
156-
scram_ClientOrServerKey(constchar*password,
157-
constchar*salt,intsaltlen,intiterations,
158-
constchar*keystr,uint8*result)
162+
scram_ClientKey(constuint8*salted_password,uint8*result)
163+
{
164+
scram_HMAC_ctxctx;
165+
166+
scram_HMAC_init(&ctx,salted_password,SCRAM_KEY_LEN);
167+
scram_HMAC_update(&ctx,"Client Key",strlen("Client Key"));
168+
scram_HMAC_final(result,&ctx);
169+
}
170+
171+
/*
172+
* Calculate ServerKey.
173+
*/
174+
void
175+
scram_ServerKey(constuint8*salted_password,uint8*result)
159176
{
160-
uint8keybuf[SCRAM_KEY_LEN];
161177
scram_HMAC_ctxctx;
162178

163-
scram_Hi(password,salt,saltlen,iterations,keybuf);
164-
scram_HMAC_init(&ctx,keybuf,SCRAM_KEY_LEN);
165-
scram_HMAC_update(&ctx,keystr,strlen(keystr));
179+
scram_HMAC_init(&ctx,salted_password,SCRAM_KEY_LEN);
180+
scram_HMAC_update(&ctx,"Server Key",strlen("Server Key"));
166181
scram_HMAC_final(result,&ctx);
167182
}

‎src/include/common/scram-common.h

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,10 @@
2929
#defineSCRAM_RAW_NONCE_LEN10
3030

3131
/* length of salt when generating new verifiers */
32-
#defineSCRAM_SALT_LEN10
32+
#defineSCRAM_DEFAULT_SALT_LEN10
3333

3434
/* default number of iterations when generating verifier */
35-
#defineSCRAM_ITERATIONS_DEFAULT4096
36-
37-
/* Base name of keys used for proof generation */
38-
#defineSCRAM_SERVER_KEY_NAME "Server Key"
39-
#defineSCRAM_CLIENT_KEY_NAME "Client Key"
35+
#defineSCRAM_DEFAULT_ITERATIONS4096
4036

4137
/*
4238
* Context data for HMAC used in SCRAM authentication.
@@ -51,9 +47,10 @@ extern void scram_HMAC_init(scram_HMAC_ctx *ctx, const uint8 *key, int keylen);
5147
externvoidscram_HMAC_update(scram_HMAC_ctx*ctx,constchar*str,intslen);
5248
externvoidscram_HMAC_final(uint8*result,scram_HMAC_ctx*ctx);
5349

50+
externvoidscram_SaltedPassword(constchar*password,constchar*salt,
51+
intsaltlen,intiterations,uint8*result);
5452
externvoidscram_H(constuint8*str,intlen,uint8*result);
55-
externvoidscram_ClientOrServerKey(constchar*password,constchar*salt,
56-
intsaltlen,intiterations,
57-
constchar*keystr,uint8*result);
53+
externvoidscram_ClientKey(constuint8*salted_password,uint8*result);
54+
externvoidscram_ServerKey(constuint8*salted_password,uint8*result);
5855

5956
#endif/* SCRAM_COMMON_H */

‎src/interfaces/libpq/fe-auth-scram.c

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ typedef struct
4646
char*password;
4747

4848
/* We construct these */
49+
uint8SaltedPassword[SCRAM_KEY_LEN];
4950
char*client_nonce;
5051
char*client_first_message_bare;
5152
char*client_final_message_without_proof;
@@ -59,7 +60,7 @@ typedef struct
5960

6061
/* These come from the server-final message */
6162
char*server_final_message;
62-
charServerProof[SCRAM_KEY_LEN];
63+
charServerSignature[SCRAM_KEY_LEN];
6364
}fe_scram_state;
6465

6566
staticboolread_server_first_message(fe_scram_state*state,char*input,
@@ -70,7 +71,7 @@ static char *build_client_first_message(fe_scram_state *state,
7071
PQExpBuffererrormessage);
7172
staticchar*build_client_final_message(fe_scram_state*state,
7273
PQExpBuffererrormessage);
73-
staticboolverify_server_proof(fe_scram_state*state);
74+
staticboolverify_server_signature(fe_scram_state*state);
7475
staticvoidcalculate_client_proof(fe_scram_state*state,
7576
constchar*client_final_message_without_proof,
7677
uint8*result);
@@ -216,12 +217,12 @@ pg_fe_scram_exchange(void *opaq, char *input, int inputlen,
216217
gotoerror;
217218

218219
/*
219-
* Verify serverproof, to make sure we're talking to the genuine
220-
* server. XXX: A fake server could simply not require
220+
* Verify serversignature, to make sure we're talking to the
221+
*genuineserver. XXX: A fake server could simply not require
221222
* authentication, though. There is currently no option in libpq
222223
* to reject a connection, if SCRAM authentication did not happen.
223224
*/
224-
if (verify_server_proof(state))
225+
if (verify_server_signature(state))
225226
*success= true;
226227
else
227228
{
@@ -486,12 +487,11 @@ read_server_first_message(fe_scram_state *state, char *input,
486487
* Read the final exchange message coming from the server.
487488
*/
488489
staticbool
489-
read_server_final_message(fe_scram_state*state,
490-
char*input,
490+
read_server_final_message(fe_scram_state*state,char*input,
491491
PQExpBuffererrormessage)
492492
{
493-
char*encoded_server_proof;
494-
intserver_proof_len;
493+
char*encoded_server_signature;
494+
intserver_signature_len;
495495

496496
state->server_final_message=strdup(input);
497497
if (!state->server_final_message)
@@ -513,8 +513,8 @@ read_server_final_message(fe_scram_state *state,
513513
}
514514

515515
/* Parse the message. */
516-
encoded_server_proof=read_attr_value(&input,'v',errormessage);
517-
if (encoded_server_proof==NULL)
516+
encoded_server_signature=read_attr_value(&input,'v',errormessage);
517+
if (encoded_server_signature==NULL)
518518
{
519519
/* read_attr_value() has generated an error message */
520520
return false;
@@ -524,13 +524,13 @@ read_server_final_message(fe_scram_state *state,
524524
printfPQExpBuffer(errormessage,
525525
libpq_gettext("malformed SCRAM message (garbage at end of server-final-message)\n"));
526526

527-
server_proof_len=pg_b64_decode(encoded_server_proof,
528-
strlen(encoded_server_proof),
529-
state->ServerProof);
530-
if (server_proof_len!=SCRAM_KEY_LEN)
527+
server_signature_len=pg_b64_decode(encoded_server_signature,
528+
strlen(encoded_server_signature),
529+
state->ServerSignature);
530+
if (server_signature_len!=SCRAM_KEY_LEN)
531531
{
532532
printfPQExpBuffer(errormessage,
533-
libpq_gettext("malformed SCRAM message (invalid serverproof)\n"));
533+
libpq_gettext("malformed SCRAM message (invalid serversignature)\n"));
534534
return false;
535535
}
536536

@@ -552,8 +552,14 @@ calculate_client_proof(fe_scram_state *state,
552552
inti;
553553
scram_HMAC_ctxctx;
554554

555-
scram_ClientOrServerKey(state->password,state->salt,state->saltlen,
556-
state->iterations,SCRAM_CLIENT_KEY_NAME,ClientKey);
555+
/*
556+
* Calculate SaltedPassword, and store it in 'state' so that we can reuse
557+
* it later in verify_server_signature.
558+
*/
559+
scram_SaltedPassword(state->password,state->salt,state->saltlen,
560+
state->iterations,state->SaltedPassword);
561+
562+
scram_ClientKey(state->SaltedPassword,ClientKey);
557563
scram_H(ClientKey,SCRAM_KEY_LEN,StoredKey);
558564

559565
scram_HMAC_init(&ctx,StoredKey,SCRAM_KEY_LEN);
@@ -575,19 +581,17 @@ calculate_client_proof(fe_scram_state *state,
575581
}
576582

577583
/*
578-
* Validate the serverproof, received as part of the final exchange message
579-
* received from the server.
584+
* Validate the serversignature, received as part of the final exchange
585+
*messagereceived from the server.
580586
*/
581587
staticbool
582-
verify_server_proof(fe_scram_state*state)
588+
verify_server_signature(fe_scram_state*state)
583589
{
584-
uint8ServerSignature[SCRAM_KEY_LEN];
590+
uint8expected_ServerSignature[SCRAM_KEY_LEN];
585591
uint8ServerKey[SCRAM_KEY_LEN];
586592
scram_HMAC_ctxctx;
587593

588-
scram_ClientOrServerKey(state->password,state->salt,state->saltlen,
589-
state->iterations,SCRAM_SERVER_KEY_NAME,
590-
ServerKey);
594+
scram_ServerKey(state->SaltedPassword,ServerKey);
591595

592596
/* calculate ServerSignature */
593597
scram_HMAC_init(&ctx,ServerKey,SCRAM_KEY_LEN);
@@ -602,9 +606,9 @@ verify_server_proof(fe_scram_state *state)
602606
scram_HMAC_update(&ctx,
603607
state->client_final_message_without_proof,
604608
strlen(state->client_final_message_without_proof));
605-
scram_HMAC_final(ServerSignature,&ctx);
609+
scram_HMAC_final(expected_ServerSignature,&ctx);
606610

607-
if (memcmp(ServerSignature,state->ServerProof,SCRAM_KEY_LEN)!=0)
611+
if (memcmp(expected_ServerSignature,state->ServerSignature,SCRAM_KEY_LEN)!=0)
608612
return false;
609613

610614
return true;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp