LCOV - code coverage report
Current view: top level - src - scram.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 58 0.0 %
Date: 2023-08-10 00:00:00 Functions: 0 5 0.0 %

          Line data    Source code
       1             : /* scram.c
       2             :  * strophe XMPP client library
       3             :  *
       4             :  * SCRAM-SHA1 helper functions according to RFC5802
       5             :  * HMAC-SHA1 implementation according to RFC2104
       6             :  *
       7             :  * Copyright (C) 2013 Dmitry Podgorny <pasis.ua@gmail.com>
       8             :  *
       9             :  *  This software is provided AS-IS with no warranty, either express
      10             :  *  or implied.
      11             :  *
      12             :  *  This program is dual licensed under the MIT and GPLv3 licenses.
      13             :  */
      14             : 
      15             : /** @file
      16             :  *  SCRAM-SHA1 helper functions.
      17             :  */
      18             : 
      19             : #include <assert.h>
      20             : #include <string.h>
      21             : 
      22             : #include "common.h"
      23             : #include "sha1.h"
      24             : #include "sha256.h"
      25             : #include "sha512.h"
      26             : #include "ostypes.h"
      27             : 
      28             : #include "scram.h"
      29             : 
      30             : #define HMAC_BLOCK_SIZE_MAX 128
      31             : 
      32             : static const uint8_t ipad = 0x36;
      33             : static const uint8_t opad = 0x5C;
      34             : 
      35             : const struct hash_alg scram_sha1 = {
      36             :     "SCRAM-SHA-1",
      37             :     SASL_MASK_SCRAMSHA1,
      38             :     SHA1_DIGEST_SIZE,
      39             :     (void (*)(const uint8_t *, size_t, uint8_t *))crypto_SHA1,
      40             :     (void (*)(void *))crypto_SHA1_Init,
      41             :     (void (*)(void *, const uint8_t *, size_t))crypto_SHA1_Update,
      42             :     (void (*)(void *, uint8_t *))crypto_SHA1_Final};
      43             : 
      44             : const struct hash_alg scram_sha256 = {
      45             :     "SCRAM-SHA-256",
      46             :     SASL_MASK_SCRAMSHA256,
      47             :     SHA256_DIGEST_SIZE,
      48             :     (void (*)(const uint8_t *, size_t, uint8_t *))sha256_hash,
      49             :     (void (*)(void *))sha256_init,
      50             :     (void (*)(void *, const uint8_t *, size_t))sha256_process,
      51             :     (void (*)(void *, uint8_t *))sha256_done};
      52             : 
      53             : const struct hash_alg scram_sha512 = {
      54             :     "SCRAM-SHA-512",
      55             :     SASL_MASK_SCRAMSHA512,
      56             :     SHA512_DIGEST_SIZE,
      57             :     (void (*)(const uint8_t *, size_t, uint8_t *))sha512_hash,
      58             :     (void (*)(void *))sha512_init,
      59             :     (void (*)(void *, const uint8_t *, size_t))sha512_process,
      60             :     (void (*)(void *, uint8_t *))sha512_done};
      61             : 
      62             : union common_hash_ctx {
      63             :     SHA1_CTX sha1;
      64             :     sha256_context sha256;
      65             :     sha512_context sha512;
      66             : };
      67             : 
      68           0 : static void crypto_HMAC(const struct hash_alg *alg,
      69             :                         const uint8_t *key,
      70             :                         size_t key_len,
      71             :                         const uint8_t *text,
      72             :                         size_t len,
      73             :                         uint8_t *digest)
      74             : {
      75           0 :     uint8_t key_pad[HMAC_BLOCK_SIZE_MAX];
      76           0 :     uint8_t key_ipad[HMAC_BLOCK_SIZE_MAX];
      77           0 :     uint8_t key_opad[HMAC_BLOCK_SIZE_MAX];
      78           0 :     uint8_t sha_digest[SCRAM_DIGEST_SIZE];
      79           0 :     size_t blocksize;
      80           0 :     size_t i;
      81           0 :     union common_hash_ctx ctx;
      82             : 
      83           0 :     assert(alg->digest_size <= HMAC_BLOCK_SIZE_MAX);
      84           0 :     blocksize = alg->digest_size < 48 ? 64 : 128;
      85             : 
      86           0 :     memset(key_pad, 0, blocksize);
      87           0 :     if (key_len <= blocksize) {
      88           0 :         memcpy(key_pad, key, key_len);
      89             :     } else {
      90             :         /* according to RFC2104 */
      91           0 :         alg->hash(key, key_len, key_pad);
      92             :     }
      93             : 
      94           0 :     for (i = 0; i < blocksize; i++) {
      95           0 :         key_ipad[i] = key_pad[i] ^ ipad;
      96           0 :         key_opad[i] = key_pad[i] ^ opad;
      97             :     }
      98             : 
      99           0 :     alg->init((void *)&ctx);
     100           0 :     alg->update((void *)&ctx, key_ipad, blocksize);
     101           0 :     alg->update((void *)&ctx, text, len);
     102           0 :     alg->final((void *)&ctx, sha_digest);
     103             : 
     104           0 :     alg->init((void *)&ctx);
     105           0 :     alg->update((void *)&ctx, key_opad, blocksize);
     106           0 :     alg->update((void *)&ctx, sha_digest, alg->digest_size);
     107           0 :     alg->final((void *)&ctx, digest);
     108           0 : }
     109             : 
     110           0 : static void SCRAM_Hi(const struct hash_alg *alg,
     111             :                      const uint8_t *text,
     112             :                      size_t len,
     113             :                      const uint8_t *salt,
     114             :                      size_t salt_len,
     115             :                      uint32_t i,
     116             :                      uint8_t *digest)
     117             : {
     118           0 :     size_t k;
     119           0 :     uint32_t j;
     120           0 :     uint8_t tmp[128];
     121             : 
     122           0 :     static uint8_t int1[] = {0x0, 0x0, 0x0, 0x1};
     123             : 
     124             :     /* assume salt + INT(1) isn't longer than sizeof(tmp) */
     125           0 :     assert(salt_len <= sizeof(tmp) - sizeof(int1));
     126             : 
     127           0 :     memset(digest, 0, alg->digest_size);
     128           0 :     if (i == 0) {
     129           0 :         return;
     130             :     }
     131             : 
     132           0 :     memcpy(tmp, salt, salt_len);
     133           0 :     memcpy(&tmp[salt_len], int1, sizeof(int1));
     134             : 
     135             :     /* 'text' for Hi is a 'key' for HMAC */
     136           0 :     crypto_HMAC(alg, text, len, tmp, salt_len + sizeof(int1), digest);
     137           0 :     memcpy(tmp, digest, alg->digest_size);
     138             : 
     139           0 :     for (j = 1; j < i; j++) {
     140           0 :         crypto_HMAC(alg, text, len, tmp, alg->digest_size, tmp);
     141           0 :         for (k = 0; k < alg->digest_size; k++) {
     142           0 :             digest[k] ^= tmp[k];
     143             :         }
     144             :     }
     145             : }
     146             : 
     147           0 : void SCRAM_ClientKey(const struct hash_alg *alg,
     148             :                      const uint8_t *password,
     149             :                      size_t len,
     150             :                      const uint8_t *salt,
     151             :                      size_t salt_len,
     152             :                      uint32_t i,
     153             :                      uint8_t *key)
     154             : {
     155           0 :     uint8_t salted[SCRAM_DIGEST_SIZE];
     156             : 
     157             :     /* XXX: Normalize(password) is omitted */
     158             : 
     159           0 :     SCRAM_Hi(alg, password, len, salt, salt_len, i, salted);
     160           0 :     crypto_HMAC(alg, salted, alg->digest_size, (uint8_t *)"Client Key",
     161             :                 strlen("Client Key"), key);
     162           0 : }
     163             : 
     164           0 : void SCRAM_ClientSignature(const struct hash_alg *alg,
     165             :                            const uint8_t *ClientKey,
     166             :                            const uint8_t *AuthMessage,
     167             :                            size_t len,
     168             :                            uint8_t *sign)
     169             : {
     170           0 :     uint8_t stored[SCRAM_DIGEST_SIZE];
     171             : 
     172           0 :     alg->hash(ClientKey, alg->digest_size, stored);
     173           0 :     crypto_HMAC(alg, stored, alg->digest_size, AuthMessage, len, sign);
     174           0 : }
     175             : 
     176           0 : void SCRAM_ClientProof(const struct hash_alg *alg,
     177             :                        const uint8_t *ClientKey,
     178             :                        const uint8_t *ClientSignature,
     179             :                        uint8_t *proof)
     180             : {
     181           0 :     size_t i;
     182           0 :     for (i = 0; i < alg->digest_size; i++) {
     183           0 :         proof[i] = ClientKey[i] ^ ClientSignature[i];
     184             :     }
     185           0 : }

Generated by: LCOV version 1.14