// Beware, this code is shared between the kernel and userspace. #ifdef _KERNEL #include #include #include #include #include #else #include #include #include #include #include #include #include #include #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