Added ksecprintf for securely printing messages from the kernel.

If SECRET_TESTING is defined, the function will compute and print
a salt value and the hmac/sha256 hash of the message, which can be
verified from the test161 server.
This commit is contained in:
Scott Haseley 2016-02-11 01:30:33 -05:00
parent 5521823176
commit 01f2d3ea2c
3 changed files with 43 additions and 42 deletions

View File

@ -45,6 +45,6 @@
*/ */
#undef SECRET_TESTING #undef SECRET_TESTING
#define SECRET 0 #define SECRET ""
#endif /* _SECRET_H_ */ #endif /* _SECRET_H_ */

View File

@ -174,7 +174,9 @@ int ll16test(int, char **);
#define SUCCESS 0 #define SUCCESS 0
#define FAIL 1 #define FAIL 1
void success(bool, uint32_t, const char *); int success(bool, const char *, const char *);
int ksecprintf(const char *secret, const char *msg, const char *name);
void random_yielder(uint32_t); void random_yielder(uint32_t);
void random_spinner(uint32_t); void random_spinner(uint32_t);

View File

@ -3,55 +3,54 @@
#include <thread.h> #include <thread.h>
#include <test.h> #include <test.h>
#include <lib.h> #include <lib.h>
#include <kern/secure.h>
/* /*
* Main success function for kernel tests. Prints a multiple of the secret if * Common success function for kernel tests. If SECRET_TESTING is defined,
* the secret is non-zero and the test succeeded. Otherwise prints a random * ksecprintf will compute the hmac/sha256 hash of any message using the
* number. * shared secret and a random salt value. The (secure) server also knows
* * the secret and can verify the message was generated by a trusted source.
* Ideally we would multiply the secret (a large prime) by another large prime * The salt value prevents against replay attacks.
* to ensure that factoring was hard, but that would require either primality
* testing (slow) or augmenting sys161 with a prime number generator. This is
* sufficient for now to prevent replay attacks.
*/ */
int
#define MIN_MULTIPLIER 0x80000000 success(bool status, const char * secret, const char * name) {
if (status == SUCCESS) {
return ksecprintf(secret, "SUCCESS", name);
} else {
return ksecprintf(secret, "FAIL", name);
}
}
#ifndef SECRET_TESTING #ifndef SECRET_TESTING
void
success(bool status, uint32_t secret, const char * name) { int
ksecprintf(const char * secret, const char * msg, const char * name)
{
(void)secret; (void)secret;
if (status == SUCCESS) { return kprintf("%s: %s\n", name, msg);
kprintf("%s: SUCCESS\n", name);
} else {
kprintf("%s: FAIL\n", name);
}
return;
} }
#else #else
void
success(bool status, uint32_t secret, const char * name) { int
uint32_t multiplier; ksecprintf(const char * secret, const char * msg, const char * name)
// Make sure we can get large random numbers {
KASSERT(randmax() == 0xffffffff); char *hash;
while (1) { char *salt;
multiplier = random(); int res;
// We can at least remove the obvious non-primes...
if (multiplier % 2 == 0) { res = hmac_salted(msg, strlen(msg), secret, strlen(secret), &hash, &salt);
continue; if (res)
} return -res;
if (multiplier > MIN_MULTIPLIER) {
break; res = kprintf("(%s, %s, %s, %s: %s)\n", name, hash, salt, name, msg);
}
} kfree(hash);
uint64_t big_secret = (uint64_t) secret * (uint64_t) multiplier; kfree(salt);
if (status == SUCCESS) {
kprintf("%s: SUCCESS (%llu)\n", name, big_secret); return res;
} else {
kprintf("%s: FAIL (%llu)\n", name, big_secret);
}
return;
} }
#endif #endif
/* /*