VirtualBox

Ignore:
Timestamp:
Nov 29, 2023 10:58:18 AM (14 months ago)
Author:
vboxsync
Message:

IPRT/crypto: Implemented handing-in crypt password strings as the salt into RTCrShaCrypt256/512(). This approach is used by many *crypt implementations -- it allows feeding the user-provided password and the crypted password from "the password file" to the function. If it returns the same crypted password then the user-provided password must be the correct one.Extended testcases. bugref:10551

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/crypto/shacrypt.cpp

    r102372 r102375  
    4848
    4949
     50/** The digest prefix for SHAcrypt256 strings. */
     51#define RT_SHACRYPT_DIGEST_PREFIX_256_STR       "$5$"
     52/** The digest prefix for SHAcrypt512 strings. */
     53#define RT_SHACRYPT_DIGEST_PREFIX_512_STR       "$6$"
     54
    5055
    5156RTR3DECL(int) RTCrShaCryptGenerateSalt(char *pszSalt, size_t cchSalt)
     
    6368
    6469
     70/**
     71 * Extracts the salt from a given string.
     72 *
     73 * @returns Pointer to the salt string, or NULL if not found / invalid.
     74 * @param   pszStr              String to extract salt from.
     75 * @param   pcchSalt            Where to reutrn the extracted salt length (in characters).
     76 */
     77static const char *rtCrShaCryptExtractSalt(const char *pszStr, size_t *pcchSalt)
     78{
     79    size_t cchSalt = strlen(pszStr);
     80
     81    /* Searches for a known SHAcrypt string prefix and skips it. */
     82#define BEGINS_WITH(a_szMatch) \
     83        (cchSalt >= sizeof(a_szMatch) - 1U && memcmp(pszStr, a_szMatch, sizeof(a_szMatch) - 1U) == 0)
     84    if (BEGINS_WITH(RT_SHACRYPT_DIGEST_PREFIX_256_STR))
     85    {
     86        cchSalt -= sizeof(RT_SHACRYPT_DIGEST_PREFIX_256_STR) - 1;
     87        pszStr  += sizeof(RT_SHACRYPT_DIGEST_PREFIX_256_STR) - 1;
     88    }
     89    else if (BEGINS_WITH(RT_SHACRYPT_DIGEST_PREFIX_512_STR))
     90    {
     91        cchSalt -= sizeof(RT_SHACRYPT_DIGEST_PREFIX_512_STR) - 1;
     92        pszStr  += sizeof(RT_SHACRYPT_DIGEST_PREFIX_512_STR) - 1;
     93    }
     94#undef BEGINS_WITH
     95
     96    /* Search for the end of the salt string, denoted by a '$'. */
     97    size_t cchLen = 0;
     98    while (   cchLen < cchSalt
     99           && pszStr[cchLen] != '$')
     100        cchLen++;
     101
     102    AssertMsgReturn(cchLen >= RT_SHACRYPT_MIN_SALT_LEN && cchLen <= RT_SHACRYPT_MAX_SALT_LEN, ("len=%zu\n", cchLen), NULL);
     103    *pcchSalt = cchLen;
     104
     105    return pszStr;
     106}
     107
     108
    65109RTR3DECL(int) RTCrShaCrypt256(const char *pszKey, const char *pszSalt, uint32_t cRounds, uint8_t abHash[RTSHA256_HASH_SIZE])
    66110{
     
    71115    size_t const cchKey     = strlen(pszKey);
    72116    AssertReturn(cchKey, VERR_INVALID_PARAMETER);
    73     size_t const cchSalt    = strlen(pszSalt);
    74     AssertMsgReturn(cchSalt >= RT_SHACRYPT_MIN_SALT_LEN && cchSalt <= RT_SHACRYPT_MAX_SALT_LEN, ("len=%zu\n", cchSalt),
    75                     VERR_INVALID_PARAMETER);
     117
     118    size_t cchSalt;
     119    pszSalt = rtCrShaCryptExtractSalt(pszSalt, &cchSalt);
     120    AssertPtrReturn(pszSalt, VERR_INVALID_PARAMETER);
    76121
    77122    uint8_t abDigest[RTSHA256_HASH_SIZE];
     
    202247    size_t cchPrefix;
    203248    if (cRounds == RT_SHACRYPT_DEFAULT_ROUNDS)
    204         cchPrefix = RTStrPrintf2(psz, cchString, "$5$%s$", pszSalt);
     249        cchPrefix = RTStrPrintf2(psz, cchString, "%s%s$", RT_SHACRYPT_DIGEST_PREFIX_256_STR, pszSalt);
    205250    else
    206         cchPrefix = RTStrPrintf2(psz, cchString, "$5$rounds=%RU32$%s$", cRounds, pszSalt);
     251        cchPrefix = RTStrPrintf2(psz, cchString, "%srounds=%RU32$%s$", RT_SHACRYPT_DIGEST_PREFIX_256_STR, cRounds, pszSalt);
    207252    AssertReturn(cchPrefix > 0, VERR_BUFFER_OVERFLOW);
    208253    AssertReturn(cch >= cchPrefix, VERR_BUFFER_OVERFLOW);
     
    255300    AssertReturn   (cRounds, VERR_INVALID_PARAMETER);
    256301
    257     size_t const cchKey     = strlen(pszKey);
     302    size_t const cchKey = strlen(pszKey);
    258303    AssertReturn(cchKey, VERR_INVALID_PARAMETER);
    259     size_t const cchSalt    = strlen(pszSalt);
    260     AssertMsgReturn(cchSalt >= RT_SHACRYPT_MIN_SALT_LEN && cchSalt <= RT_SHACRYPT_MAX_SALT_LEN, ("len=%zu\n", cchSalt),
    261                     VERR_INVALID_PARAMETER);
     304
     305    size_t cchSalt;
     306    pszSalt = rtCrShaCryptExtractSalt(pszSalt, &cchSalt);
     307    AssertPtrReturn(pszSalt, VERR_INVALID_PARAMETER);
    262308
    263309    uint8_t abDigest[RTSHA512_HASH_SIZE];
     
    386432    size_t cchPrefix;
    387433    if (cRounds == RT_SHACRYPT_DEFAULT_ROUNDS)
    388         cchPrefix = RTStrPrintf2(psz, cchString, "$6$%s$", pszSalt);
     434        cchPrefix = RTStrPrintf2(psz, cchString, "%s%s$", RT_SHACRYPT_DIGEST_PREFIX_512_STR, pszSalt);
    389435    else
    390         cchPrefix = RTStrPrintf2(psz, cchString, "$6$rounds=%RU32$%s$", cRounds, pszSalt);
     436        cchPrefix = RTStrPrintf2(psz, cchString, "%srounds=%RU32$%s$", RT_SHACRYPT_DIGEST_PREFIX_512_STR, cRounds, pszSalt);
    391437    AssertReturn(cchPrefix > 0, VERR_BUFFER_OVERFLOW);
    392438    AssertReturn(cch >= cchPrefix, VERR_BUFFER_OVERFLOW);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette