137 lines
2.8 KiB
C
137 lines
2.8 KiB
C
// Beware, this code is shared between the kernel and userspace.
|
|
|
|
#ifdef _KERNEL
|
|
#include <types.h>
|
|
#include <lib.h>
|
|
#include <kern/errno.h>
|
|
#include <kern/secure.h>
|
|
#include <kern/test161.h>
|
|
#else
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <test161/test161.h>
|
|
#include <test161/secure.h>
|
|
#endif
|
|
|
|
// Hack for allocating userspace memory without malloc.
|
|
#define BUFFER_SIZE 4096
|
|
|
|
#ifndef _KERNEL
|
|
static char temp_buffer[BUFFER_SIZE];
|
|
static char write_buffer[BUFFER_SIZE];
|
|
#endif
|
|
|
|
static inline void * _alloc(size_t size)
|
|
{
|
|
#ifdef _KERNEL
|
|
return kmalloc(size);
|
|
#else
|
|
(void)size;
|
|
return temp_buffer;
|
|
#endif
|
|
}
|
|
|
|
static inline void _free(void *ptr)
|
|
{
|
|
#ifdef _KERNEL
|
|
kfree(ptr);
|
|
#else
|
|
(void)ptr;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Common success function for kernel tests. If SECRET_TESTING is defined,
|
|
* ksecprintf will compute the hmac/sha256 hash of any message using the
|
|
* 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.
|
|
* The salt value prevents against replay attacks.
|
|
*/
|
|
int
|
|
success(int status, const char * secret, const char * name) {
|
|
if (status == TEST161_SUCCESS) {
|
|
return secprintf(secret, "SUCCESS", name);
|
|
} else {
|
|
return secprintf(secret, "FAIL", name);
|
|
}
|
|
}
|
|
|
|
int
|
|
partial_credit(const char *secret, const char *name, int scored, int total)
|
|
{
|
|
char buffer[128];
|
|
snprintf(buffer, 128, "PARTIAL CREDIT %d OF %d", scored, total);
|
|
return secprintf(secret, buffer, name);
|
|
}
|
|
#ifndef _KERNEL
|
|
|
|
// Borrowed from parallelvm. We need atomic console writes so our
|
|
// output doesn't get intermingled since test161 works with lines.
|
|
static
|
|
int
|
|
say(const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
vsnprintf(write_buffer, BUFFER_SIZE, fmt, ap);
|
|
va_end(ap);
|
|
return write(STDOUT_FILENO, write_buffer, strlen(write_buffer));
|
|
}
|
|
#endif
|
|
|
|
#ifndef SECRET_TESTING
|
|
|
|
int
|
|
secprintf(const char * secret, const char * msg, const char * name)
|
|
{
|
|
(void)secret;
|
|
|
|
#ifdef _KERNEL
|
|
return kprintf("%s: %s\n", name, msg);
|
|
#else
|
|
return say("%s: %s\n", name, msg);
|
|
#endif
|
|
}
|
|
|
|
#else
|
|
|
|
int
|
|
secprintf(const char * secret, const char * msg, const char * name)
|
|
{
|
|
char *hash, *salt, *fullmsg;
|
|
int res;
|
|
size_t len;
|
|
|
|
hash = salt = fullmsg = NULL;
|
|
|
|
// test161 expects "name: msg"
|
|
len = strlen(name) + strlen(msg) + 3; // +3 for " :" and null terminator
|
|
fullmsg = (char *)_alloc(len);
|
|
if (fullmsg == NULL) {
|
|
return -ENOMEM;
|
|
}
|
|
snprintf(fullmsg, len, "%s: %s", name, msg);
|
|
|
|
res = hmac_salted(fullmsg, len-1, secret, strlen(secret), &hash, &salt);
|
|
if (res)
|
|
return -res;
|
|
|
|
#ifdef _KERNEL
|
|
res = kprintf("(%s, %s, %s, %s: %s)\n", name, hash, salt, name, msg);
|
|
#else
|
|
res = say("(%s, %s, %s, %s: %s)\n", name, hash, salt, name, msg);
|
|
#endif
|
|
|
|
_free(hash);
|
|
_free(salt);
|
|
_free(fullmsg);
|
|
|
|
return res;
|
|
}
|
|
|
|
#endif
|