Changeset 102488 in vbox for trunk/src/VBox/Runtime/testcase
- Timestamp:
- Dec 5, 2023 11:53:09 PM (15 months ago)
- svn:sync-xref-src-repo-rev:
- 160631
- Location:
- trunk/src/VBox/Runtime/testcase
- Files:
-
- 1 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/testcase/Makefile.kmk
r102289 r102488 77 77 tstRTCritSectRw \ 78 78 tstRTCrPkix-1 \ 79 tstRTCrShaCrypt \ 79 80 tstRTCrX509-1 \ 80 81 tstRTCType \ … … 144 145 tstRTSemXRoads \ 145 146 tstRTSg \ 146 tstRTShaCrypt \147 147 tstRTSort \ 148 148 tstRTStrAlloc \ … … 838 838 tstRTSg_SOURCES = tstRTSg.cpp 839 839 840 tstRT ShaCrypt_TEMPLATE = VBoxR3TstExe841 tstRT ShaCrypt_SOURCES = tstRTShaCrypt.cpp840 tstRTCrShaCrypt_TEMPLATE = VBoxR3TstExe 841 tstRTCrShaCrypt_SOURCES = tstRTCrShaCrypt.cpp 842 842 843 843 tstRTSort_TEMPLATE = VBoxR3TstExe -
trunk/src/VBox/Runtime/testcase/tstRTCrShaCrypt.cpp
r102476 r102488 40 40 *********************************************************************************************************************************/ 41 41 #include <iprt/crypto/shacrypt.h> 42 42 43 #include <iprt/errcore.h> 43 44 #include <iprt/initterm.h> 44 45 #include <iprt/rand.h> 45 #include <iprt/sha.h>46 46 #include <iprt/string.h> 47 47 #include <iprt/test.h> 48 49 50 /*********************************************************************************************************************************51 * Global Variables *52 *********************************************************************************************************************************/53 static RTTEST g_hTest;54 48 55 49 … … 59 53 60 54 /** Digest type. */ 61 typedef enum TST _DIGESTTYPE62 { 63 TST _DIGESTTYPE_RANDOM = 0,64 TST _DIGESTTYPE_SHA256,65 TST _DIGESTTYPE_SHA512,66 TST _DIGESTTYPE_LAST67 } TST _DIGESTTYPE;55 typedef enum TSTDIGESTTYPE 56 { 57 TSTDIGESTTYPE_RANDOM = 0, 58 TSTDIGESTTYPE_SHA256, 59 TSTDIGESTTYPE_SHA512, 60 TSTDIGESTTYPE_END 61 } TSTDIGESTTYPE; 68 62 69 63 static struct … … 76 70 uint32_t cRounds; 77 71 /** Digest type to use. If set to 0, a random digest type will be used. */ 78 TST _DIGESTTYPEenmType;72 TSTDIGESTTYPE enmType; 79 73 /** Overall test outcome. */ 80 int rc;74 int rc; 81 75 /** Expected result as a string. Can be NULL to skip testing this. */ 82 const char *pszResultStr;76 const char *pszResult; 83 77 } g_aTests[] = 84 78 { … … 87 81 */ 88 82 { /* No salt */ 89 /* pszPassword */"changeme",90 /* pszSalt */"",91 /* cRounds */ RT_SHACRYPT_DEFAULT_ROUNDS,92 /* enmType */ TST_DIGESTTYPE_RANDOM,93 /* rc */ VERR_INVALID_PARAMETER,94 /* pszResultStr */""83 /* .pszPassword = */ "changeme", 84 /* .pszSalt = */ "", 85 /* .cRounds = */ RT_SHACRYPT_ROUNDS_DEFAULT, 86 /* .enmType = */ TSTDIGESTTYPE_RANDOM, 87 /* .rc = */ VERR_BUFFER_UNDERFLOW, 88 /* .pszResult = */ "" 95 89 }, 96 90 { /* Salt too short */ 97 /* pszPassword */"changeme",98 /* pszSalt */"1234",99 /* cRounds */ RT_SHACRYPT_DEFAULT_ROUNDS,100 /* enmType */ TST_DIGESTTYPE_RANDOM,101 /* rc */ VERR_INVALID_PARAMETER,102 /* pszResultStr */""91 /* .pszPassword = */ "changeme", 92 /* .pszSalt = */ "1234", 93 /* .cRounds = */ RT_SHACRYPT_ROUNDS_DEFAULT, 94 /* .enmType = */ TSTDIGESTTYPE_RANDOM, 95 /* .rc = */ VERR_BUFFER_UNDERFLOW, 96 /* .pszResult = */ "" 103 97 }, 104 98 { /* Salt too long */ 105 /* pszPassword */"changeme",106 /* pszSalt */"12341234123412341234123412341234",107 /* cRounds */ RT_SHACRYPT_DEFAULT_ROUNDS,108 /* enmType */ TST_DIGESTTYPE_RANDOM,109 /* rc */ VERR_INVALID_PARAMETER,110 /* pszResultStr */""99 /* .pszPassword = */ "changeme", 100 /* .pszSalt = */ "12341234123412341234123412341234", 101 /* .cRounds = */ RT_SHACRYPT_ROUNDS_DEFAULT, 102 /* .enmType = */ TSTDIGESTTYPE_RANDOM, 103 /* .rc = */ VERR_TOO_MUCH_DATA, 104 /* .pszResult = */ "" 111 105 }, 112 106 { /* Invalid rounds */ 113 /* pszPassword */"changeme",114 /* pszSalt */ "12341234123412341234123412341234",115 /* cRounds */ 0,116 /* enmType */ TST_DIGESTTYPE_RANDOM,117 /* rc */ VERR_INVALID_PARAMETER,118 /* pszResultStr */""107 /* .pszPassword = */ "changeme", 108 /* .pszSalt = */ "0123456789abcdef", 109 /* .cRounds = */ 42, 110 /* .enmType = */ TSTDIGESTTYPE_RANDOM, 111 /* .rc = */ VERR_OUT_OF_RANGE, 112 /* .pszResult = */ "" 119 113 }, 120 114 /* 121 115 * Valid stuff. 122 116 */ 123 { /* Expected string */ 124 /* pszPassword */ "changeme", 125 /* pszSalt */ "foo12345", 126 /* cRounds */ RT_SHACRYPT_DEFAULT_ROUNDS, 127 /* enmType */ TST_DIGESTTYPE_SHA256, 128 /* rc */ VINF_SUCCESS, 129 /* pszResultStr */ "$5$foo12345$KnOIYJmTgZ744xCqNLl1I9qF.Xq47vHTH.yVStiAMZD" 130 }, 131 { /* Expected string */ 132 /* pszPassword */ "changeme", 133 /* pszSalt */ "foo12345", 134 /* cRounds */ RT_SHACRYPT_DEFAULT_ROUNDS, 135 /* enmType */ TST_DIGESTTYPE_SHA512, 136 /* rc */ VINF_SUCCESS, 137 /* pszResultStr */ "$6$foo12345$cb11CtCP6YgoZr8SyNoD2TAdOY4OmTzA6kfDgju5JrNVzgeCBU1ALbJHVlEuSImPKAoSnT53N7k7BqzjYRRPk/" 138 }, 139 { /* Custom rounds */ 140 /* pszPassword */ "changeme", 141 /* pszSalt */ "foo12345", 142 /* cRounds */ 42, 143 /* enmType */ TST_DIGESTTYPE_RANDOM, 144 /* rc */ VINF_SUCCESS, 145 /* pszResultStr */ NULL 146 }, 147 { /* Random salt + rounds */ 148 /* pszPassword */ "changeme", 149 /* pszSalt */ NULL, 150 /* cRounds */ UINT32_MAX, 151 /* enmType */ TST_DIGESTTYPE_RANDOM, 152 /* rc */ VINF_SUCCESS, 153 /* pszResultStr */ NULL 154 }, 155 { /* Random salt */ 156 /* pszPassword */ "changeme", 157 /* pszSalt */ NULL, 158 /* cRounds */ RT_SHACRYPT_DEFAULT_ROUNDS, 159 /* enmType */ TST_DIGESTTYPE_RANDOM, 160 /* rc */ VINF_SUCCESS, 161 /* pszResultStr */ NULL 117 { 118 /* .pszPassword = */ "changeme", 119 /* .pszSalt = */ "foo12345", 120 /* .cRounds = */ RT_SHACRYPT_ROUNDS_DEFAULT, 121 /* .enmType = */ TSTDIGESTTYPE_SHA256, 122 /* .rc = */ VINF_SUCCESS, 123 /* .pszResult = */ "$5$foo12345$KnOIYJmTgZ744xCqNLl1I9qF.Xq47vHTH.yVStiAMZD" 124 }, 125 { 126 /* .pszPassword = */ "really-secure-semi-long-password", 127 /* .pszSalt = */ "5288d4774fd14289", 128 /* .cRounds = */ 999663, 129 /* .enmType = */ TSTDIGESTTYPE_SHA256, 130 /* .rc = */ VINF_SUCCESS, 131 /* .pszResult = */ "$5$rounds=999663$5288d4774fd14289$KkMAAPiAFgo9bFHnd79MCnBmMeJXlx02ra4e/20WoC4" 132 }, 133 { 134 /* .pszPassword = */ "changeme", 135 /* .pszSalt = */ "foo12345", 136 /* .cRounds = */ RT_SHACRYPT_ROUNDS_DEFAULT, 137 /* .enmType = */ TSTDIGESTTYPE_SHA512, 138 /* .rc = */ VINF_SUCCESS, 139 /* .pszResult = */ "$6$foo12345$cb11CtCP6YgoZr8SyNoD2TAdOY4OmTzA6kfDgju5JrNVzgeCBU1ALbJHVlEuSImPKAoSnT53N7k7BqzjYRRPk/" 140 }, 141 { 142 /* .pszPassword = */ "really-really-really-really-really-long-and-still-insecure-password", 143 /* .pszSalt = */ "$6$rounds=384836$AbCdEfGhijKLM", 144 /* .cRounds = */ RT_SHACRYPT_ROUNDS_DEFAULT, 145 /* .enmType = */ TSTDIGESTTYPE_SHA512, 146 /* .rc = */ VINF_SUCCESS, 147 /* .pszResult = */ "$6$rounds=384836$AbCdEfGhijKLM$pJM6Ugvo4IiVCd8KTmDNIvShHX.G6p0SC/FnBNBAf9TBm1Td/s9HsVu.iWiEBxnEDWiB5zn/NBi6VTqhCP7Ii0" 148 }, 149 { 150 /* .pszPassword = */ "이것은 테스트입니다", /* "This is a test" in Korean */ 151 /* .pszSalt = */ "foo12345", 152 /* .cRounds = */ RT_SHACRYPT_ROUNDS_DEFAULT, 153 /* .enmType = */ TSTDIGESTTYPE_SHA256, 154 /* .rc = */ VINF_SUCCESS, 155 /* .pszResult = */ "$5$foo12345$7fumMsJKgCGipks2nNPi185ANXwfTf9Ilz70J4wKqe1" 156 }, 157 { 158 /* .pszPassword = */ "이것은 테스트입니다", /* "This is a test" in Korean */ 159 /* .pszSalt = */ "foo12345", 160 /* .cRounds = */ RT_SHACRYPT_ROUNDS_DEFAULT, 161 /* .enmType = */ TSTDIGESTTYPE_SHA512, 162 /* .rc = */ VINF_SUCCESS, 163 /* .pszResult = */ "$6$foo12345$IWlIz4tyl39ETRpKlQ.R42tdeB2Ax9gz9sazAynilHDFm0zXUdsrm4nXzdlSd5jJhvwV7EPSc./2pBNoL1PIw1" 164 }, 165 { 166 /* .pszPassword = */ "changeme", 167 /* .pszSalt = */ "foo12345", 168 /* .cRounds = */ 40000, 169 /* .enmType = */ TSTDIGESTTYPE_RANDOM, 170 /* .rc = */ VINF_SUCCESS, 171 /* .pszResult = */ NULL 172 }, 173 { 174 /* .pszPassword = */ "changeme", 175 /* .pszSalt = */ NULL, 176 /* .cRounds = */ UINT32_MAX, 177 /* .enmType = */ TSTDIGESTTYPE_RANDOM, 178 /* .rc = */ VINF_SUCCESS, 179 /* .pszResult = */ NULL 180 }, 181 { 182 /* .pszPassword = */ "changeme", 183 /* .pszSalt = */ NULL, 184 /* .cRounds = */ RT_SHACRYPT_ROUNDS_DEFAULT, 185 /* .enmType = */ TSTDIGESTTYPE_RANDOM, 186 /* .rc = */ VINF_SUCCESS, 187 /* .pszResult = */ NULL 162 188 } 163 189 }; 190 191 192 static void test1(RTTEST hTest) 193 { 194 RTTestDisableAssertions(hTest); 195 196 char *pszGuardedSalt = NULL; 197 int rc = RTTestGuardedAlloc(hTest, RT_SHACRYPT_SALT_MAX_LEN + 1, 1, false, (void **)&pszGuardedSalt); 198 RTTESTI_CHECK_RC_OK_RETV(rc); 199 200 char *pszGuardedResult = NULL; 201 rc = RTTestGuardedAlloc(hTest, RT_SHACRYPT_512_MAX_SIZE, 1, false, (void **)&pszGuardedResult); 202 RTTESTI_CHECK_RC_OK_RETV(rc); 203 204 for (uint32_t i = 0; i < RT_ELEMENTS(g_aTests); i++) 205 { 206 const char *pszSalt = g_aTests[i].pszSalt; 207 if (!pszSalt) 208 { 209 uint32_t const cchSalt = RTRandU32Ex(RT_SHACRYPT_SALT_MIN_LEN, RT_SHACRYPT_SALT_MAX_LEN); 210 rc = RTCrShaCryptGenerateSalt(&pszGuardedSalt[RT_SHACRYPT_SALT_MAX_LEN - cchSalt], cchSalt); 211 RTTEST_CHECK_RC_OK(hTest, rc); 212 pszSalt = &pszGuardedSalt[RT_SHACRYPT_SALT_MAX_LEN - cchSalt]; 213 } 214 215 uint32_t cRounds = g_aTests[i].cRounds; 216 if (cRounds == UINT32_MAX) 217 cRounds = RTRandU32Ex(RT_SHACRYPT_ROUNDS_MIN, _512K /* Save a bit of time on the testboxes */); 218 219 TSTDIGESTTYPE enmType = g_aTests[i].enmType; 220 if (enmType == TSTDIGESTTYPE_RANDOM) 221 enmType = (TSTDIGESTTYPE)RTRandU32Ex(TSTDIGESTTYPE_RANDOM + 1, TSTDIGESTTYPE_END - 1); 222 223 uint8_t abDigest[RTSHA512_HASH_SIZE]; 224 switch (enmType) 225 { 226 case TSTDIGESTTYPE_SHA256: 227 rc = RTCrShaCrypt256Ex(g_aTests[i].pszPassword, pszSalt, cRounds, abDigest); 228 break; 229 230 case TSTDIGESTTYPE_SHA512: 231 rc = RTCrShaCrypt512Ex(g_aTests[i].pszPassword, pszSalt, cRounds, abDigest); 232 break; 233 234 default: 235 AssertFailedStmt(rc = VERR_INTERNAL_ERROR); 236 break; 237 } 238 if (rc != g_aTests[i].rc) 239 RTTestIFailed("#%u: RTCrShaCryptXxxEx(,%s,%#x,) returns %Rrc, expected %Rrc", 240 i, pszSalt, cRounds, rc, g_aTests[i].rc); 241 242 if (RT_SUCCESS(rc)) 243 { 244 RT_BZERO(pszGuardedResult, RT_SHACRYPT_512_MAX_SIZE); 245 switch (enmType) 246 { 247 case TSTDIGESTTYPE_SHA256: 248 rc = RTCrShaCrypt256ToString(abDigest, pszSalt, cRounds, pszGuardedResult, RT_SHACRYPT_512_MAX_SIZE); 249 break; 250 251 case TSTDIGESTTYPE_SHA512: 252 rc = RTCrShaCrypt512ToString(abDigest, pszSalt, cRounds, pszGuardedResult, RT_SHACRYPT_512_MAX_SIZE); 253 break; 254 255 default: 256 AssertFailedStmt(rc = VERR_INTERNAL_ERROR); 257 break; 258 } 259 if (RT_SUCCESS(rc)) 260 { 261 if (g_aTests[i].pszResult && strcmp(pszGuardedResult, g_aTests[i].pszResult)) 262 RTTestIFailed("#%u: RTCrShaCryptXxxString returns '%s', expected '%s'", 263 i, pszGuardedResult, g_aTests[i].pszResult); 264 265 /* 266 * Do a verification round, where we pass the above result in as the salt. 267 */ 268 char szResult2[RT_SHACRYPT_512_MAX_SIZE] = {0}; 269 switch (enmType) 270 { 271 case TSTDIGESTTYPE_SHA256: 272 rc = RTCrShaCrypt256(g_aTests[i].pszPassword, pszGuardedResult, cRounds, szResult2, sizeof(szResult2)); 273 break; 274 275 case TSTDIGESTTYPE_SHA512: 276 rc = RTCrShaCrypt512(g_aTests[i].pszPassword, pszGuardedResult, cRounds, szResult2, sizeof(szResult2)); 277 break; 278 279 default: 280 AssertFailed(); 281 break; 282 } 283 284 if (strcmp(szResult2, pszGuardedResult)) 285 RTTestIFailed("#%u (result as salt): Returns '%s', expected '%s'", i, szResult2, pszGuardedResult); 286 287 /* 288 * Push the buffer limit on the string formatter. 289 */ 290 size_t const cchNeeded = strlen(szResult2); 291 size_t const cbBufMax = RT_MIN(RT_SHACRYPT_512_MAX_SIZE, cchNeeded + 32); 292 for (size_t cbBuf = 0; cbBuf <= cbBufMax; cbBuf++) 293 { 294 char * const pszBuf = &pszGuardedResult[RT_SHACRYPT_512_MAX_SIZE - cbBuf]; 295 switch (enmType) 296 { 297 case TSTDIGESTTYPE_SHA256: 298 rc = RTCrShaCrypt256ToString(abDigest, pszSalt, cRounds, pszBuf, cbBuf); 299 break; 300 case TSTDIGESTTYPE_SHA512: 301 rc = RTCrShaCrypt512ToString(abDigest, pszSalt, cRounds, pszBuf, cbBuf); 302 break; 303 default: 304 AssertFailedStmt(rc = VERR_INTERNAL_ERROR); 305 break; 306 } 307 int rcExpect = cbBuf <= cchNeeded ? VERR_BUFFER_OVERFLOW : VINF_SUCCESS; 308 if (rc != rcExpect) 309 RTTestIFailed("#%u: cbBuf=%#zx cchNeeded=%#zx: %Rrc, expected %Rrc", i, cbBuf, cchNeeded, rc, rcExpect); 310 if (cbBuf > cchNeeded && memcmp(pszBuf, szResult2, cchNeeded + 1)) 311 RTTestIFailed("#%u: cbBuf=%#zx cchNeeded=%#zx: '%s', expected '%s'", 312 i, cbBuf, cchNeeded, pszBuf, szResult2); 313 } 314 } 315 else 316 RTTestIFailed("#%u: RTCrShaCryptXxxString returns %Rrc", i, rc); 317 } 318 } 319 320 RTTestRestoreAssertions(hTest); 321 } 164 322 165 323 … … 170 328 */ 171 329 RTTEST hTest; 172 int rc= RTTestInitAndCreate("tstRTShaCrypt", &hTest);173 if (rc )174 return rc ;330 RTEXITCODE rcExit = RTTestInitAndCreate("tstRTShaCrypt", &hTest); 331 if (rcExit != RTEXITCODE_SUCCESS) 332 return rcExit; 175 333 RTTestBanner(hTest); 176 g_hTest = hTest; 177 178 bool const fAssertMayPanic = RTAssertMayPanic(); 179 RTAssertSetMayPanic(false); /* To test invalid stuff. */ 180 bool const fAssertQuiet = RTAssertAreQuiet(); 181 RTAssertSetQuiet(true); /* Ditto. */ 182 183 char szSalt[RT_SHACRYPT_MAX_SALT_LEN + 1]; 184 uint8_t abDigest[RTSHA512_HASH_SIZE]; 185 186 for (uint32_t i = 0; i < RT_ELEMENTS(g_aTests); i++) 187 { 188 const char *pszSalt; 189 if (g_aTests[i].pszSalt) 190 pszSalt = g_aTests[i].pszSalt; 191 else 192 { 193 rc = RTCrShaCryptGenerateSalt(szSalt, RT_SHACRYPT_MAX_SALT_LEN); 194 RTTEST_CHECK_RC_OK(hTest, rc); 195 pszSalt = szSalt; 196 } 197 198 uint32_t cRounds; 199 if (g_aTests[i].cRounds == UINT32_MAX) 200 cRounds = RTRandU32Ex(1, _512K /* Save a bit of time on the testboxes */); 201 else 202 cRounds = g_aTests[i].cRounds; 203 204 TST_DIGESTTYPE enmType; 205 if (g_aTests[i].enmType == TST_DIGESTTYPE_RANDOM) 206 enmType = (TST_DIGESTTYPE)RTRandU32Ex(1, TST_DIGESTTYPE_LAST - 1); 207 else 208 enmType = g_aTests[i].enmType; 209 210 switch (enmType) 211 { 212 case TST_DIGESTTYPE_SHA256: 213 rc = RTCrShaCrypt256(g_aTests[i].pszPassword, pszSalt, cRounds, abDigest); 214 break; 215 216 case TST_DIGESTTYPE_SHA512: 217 rc = RTCrShaCrypt512(g_aTests[i].pszPassword, pszSalt, cRounds, abDigest); 218 break; 219 220 default: 221 AssertFailed(); 222 break; 223 } 224 225 if ( RT_SUCCESS(rc) 226 && g_aTests[i].pszResultStr) 227 { 228 char szResult[RTSHA512_DIGEST_LEN + 1]; 229 230 switch (enmType) 231 { 232 case TST_DIGESTTYPE_SHA256: 233 rc = RTCrShaCrypt256ToString(abDigest, pszSalt, cRounds, szResult, sizeof(szResult)); 234 break; 235 236 case TST_DIGESTTYPE_SHA512: 237 rc = RTCrShaCrypt512ToString(abDigest, pszSalt, cRounds, szResult, sizeof(szResult)); 238 break; 239 240 default: 241 AssertFailed(); 242 break; 243 } 244 245 if (RT_SUCCESS(rc)) 246 { 247 if (RTStrCmp(szResult, g_aTests[i].pszResultStr)) 248 RTTestIFailed("#%u: Returns '%s', expected '%s'", i, szResult, g_aTests[i].pszResultStr); 249 250 /* Now do the same, but hand-in the result string as the salt. 251 * 252 * This approach is used by many *crypt implementations -- it allows feeding the user-provided password and the 253 * crypted password from "the password file" to the function. If it returns the same crypted password then the 254 * user-provided password must be the correct one. 255 */ 256 switch (enmType) 257 { 258 case TST_DIGESTTYPE_SHA256: 259 { 260 rc = RTCrShaCrypt256(g_aTests[i].pszPassword, g_aTests[i].pszResultStr, cRounds, abDigest); 261 if (RT_SUCCESS(rc)) 262 rc = RTCrShaCrypt256ToString(abDigest, pszSalt, cRounds, szResult, sizeof(szResult)); 263 break; 264 } 265 266 case TST_DIGESTTYPE_SHA512: 267 { 268 rc = RTCrShaCrypt512(g_aTests[i].pszPassword, g_aTests[i].pszResultStr, cRounds, abDigest); 269 if (RT_SUCCESS(rc)) 270 rc = RTCrShaCrypt512ToString(abDigest, pszSalt, cRounds, szResult, sizeof(szResult)); 271 break; 272 } 273 274 default: 275 AssertFailed(); 276 break; 277 } 278 279 if (RTStrCmp(szResult, g_aTests[i].pszResultStr)) 280 RTTestIFailed("#%u (result as salt): Returns '%s', expected '%s'", 281 i, szResult, g_aTests[i].pszResultStr); 282 } 283 } 284 285 if (rc != g_aTests[i].rc) 286 RTTestIFailed("#%u: Returned %Rrc, expected %Rrc", i, rc, g_aTests[i].rc); 287 } 288 289 RTAssertSetMayPanic(fAssertMayPanic); 290 RTAssertSetQuiet(fAssertQuiet); 334 335 test1(hTest); 291 336 292 337 /*
Note:
See TracChangeset
for help on using the changeset viewer.