/* get_string * * This gets a printable string from the memory buffer. * It searchs backwards for a non-printable character or a NULL terminator. * * inputs: * * str/len - the buffer to store the string in. * * ret: * * -1 - we couldn't find the string. * 0 - success */ int get_string(char *str, int len) { int i, j; char c; for (i = 0; i < len; i++) { fb_peek(str + i, 1); if (fb_seek_dec(1) != 0) return -1; if (!str[i]) break; if (!isprint(str[i])) return -1; } if (i == 0 || i >= len) return -1; /* We read string in reverse order, so reverse it again */ for (j=0; j<i/2; j++) { c = str[j]; str[j] = str[i-j-1]; str[i-j-1] = c; } return 0; }
/* * Check the crypto signature on the image... * This always includes a public key encrypted header and an MD5 * (or SHA256) checksum. It optionally includes AES encryption of * the image. */ static int check_crypto_signature(void) { struct header hdr; int hash_length; unsigned long fblength, length; unsigned char *data; RSA *pkey; #ifdef CONFIG_USER_NETFLASH_CRYPTO_V2 unsigned char hash[SHA256_DIGEST_LENGTH]; #else unsigned char hash[MD5_DIGEST_LENGTH]; #endif if (!load_public_key(&pkey)) return CRYPTO_CHECK_NO_PUBLICKEY; if (!decode_header_info(&hdr, pkey, &hash_length)) return CRYPTO_CHECK_NO_HEADER; RSA_free(pkey); /* Decrypt image if needed */ if (hdr.flags & FLAG_ENCRYPTED) { unsigned char cin[AES_BLOCK_SIZE]; unsigned char cout[AES_BLOCK_SIZE]; unsigned long s; AES_KEY key; if (fb_seek_set(0) < 0) { error("Can not decrypt encrypted image when -t option is used."); exit(BAD_CRYPT); } if ((hash_length % AES_BLOCK_SIZE) != 0) { error("image size not miscable with cryptography"); exit(BAD_CRYPT); } AES_set_decrypt_key(hdr.aeskey, AESKEYSIZE * 8, &key); /* Convert the body of the file */ for (s = 0; s < hash_length; s += AES_BLOCK_SIZE) { fb_peek(cin, AES_BLOCK_SIZE); AES_decrypt(cin, cout, &key); fb_write(cout, AES_BLOCK_SIZE); } } /* Remove padding */ if (hdr.padsize) { hash_length -= hdr.padsize; #ifdef CONFIG_USER_NETFLASH_CRYPTO_V2 fb_meta_add(hdr.padsize); #else fb_trim(hdr.padsize); #endif } if (crypto_hash_init) { if (crypto_hash_total > hash_length) { error("hashed too much, try without -t"); exit(BAD_MD5_SIG); } fb_seek_set(crypto_hash_total); } else { #ifdef CONFIG_USER_NETFLASH_CRYPTO_V2 SHA256_Init(&sha_ctx); #else MD5_Init(&md5_ctx); #endif fb_seek_set(0); } while ((data = fb_read_block(&fblength)) != NULL) { length = fblength; if (length > (hash_length - crypto_hash_total)) { length = hash_length - crypto_hash_total; } #ifdef CONFIG_USER_NETFLASH_CRYPTO_V2 SHA256_Update(&sha_ctx, data, length); #else MD5_Update(&md5_ctx, data, length); #endif if (length != fblength) break; crypto_hash_total += length; } #ifdef CONFIG_USER_NETFLASH_CRYPTO_V2 SHA256_Final(hash, &sha_ctx); if (memcmp(hdr.hash, hash, SHA256_DIGEST_LENGTH) != 0) { error("bad SHA256 signature"); exit(BAD_MD5_SIG); } #else MD5_Final(hash, &md5_ctx); if (memcmp(hdr.md5, hash, MD5_DIGEST_LENGTH) != 0) { error("bad MD5 signature"); exit(BAD_MD5_SIG); } #endif notice("signed image approved"); return CRYPTO_CHECK_OK; }