void BRSHA384(void *md48, const void *data, size_t len) { size_t i; uint64_t x[16], buf[] = { 0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939, 0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4 }; assert(md48 != NULL); assert(data != NULL || len == 0); for (i = 0; i < len; i += 128) { // process data in 128 byte blocks memcpy(x, (const uint8_t *)data + i, (i + 128 < len) ? 128 : len - i); if (i + 128 > len) break; _BRSHA512Compress(buf, x); } memset((uint8_t *)x + (len - i), 0, 128 - (len - i)); // clear remainder of x ((uint8_t *)x)[len - i] = 0x80; // append padding if (len - i >= 112) _BRSHA512Compress(buf, x), memset(x, 0, 128); // length goes to next block x[14] = 0, x[15] = be64((uint64_t)len*8); // append length in bits _BRSHA512Compress(buf, x); // finalize for (i = 0; i < 6; i++) buf[i] = be64(buf[i]); // endian swap memcpy(md48, buf, 48); // write to md mem_clean(x, sizeof(x)); mem_clean(buf, sizeof(buf)); }
void BRSHA256(void *md32, const void *data, size_t len) { size_t i; uint32_t x[16], buf[] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; // initial buffer values assert(md32 != NULL); assert(data != NULL || len == 0); for (i = 0; i < len; i += 64) { // process data in 64 byte blocks memcpy(x, (const uint8_t *)data + i, (i + 64 < len) ? 64 : len - i); if (i + 64 > len) break; _BRSHA256Compress(buf, x); } memset((uint8_t *)x + (len - i), 0, 64 - (len - i)); // clear remainder of x ((uint8_t *)x)[len - i] = 0x80; // append padding if (len - i >= 56) _BRSHA256Compress(buf, x), memset(x, 0, 64); // length goes to next block x[14] = be32((uint32_t)(len >> 29)), x[15] = be32((uint32_t)(len << 3)); // append length in bits _BRSHA256Compress(buf, x); // finalize for (i = 0; i < 8; i++) buf[i] = be32(buf[i]); // endian swap memcpy(md32, buf, 32); // write to md mem_clean(x, sizeof(x)); mem_clean(buf, sizeof(buf)); }
void BRSHA512(void *md64, const void *data, size_t len) { size_t i; uint64_t x[16], buf[] = { 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179 }; assert(md64 != NULL); assert(data != NULL || len == 0); for (i = 0; i < len; i += 128) { // process data in 128 byte blocks memcpy(x, (const uint8_t *)data + i, (i + 128 < len) ? 128 : len - i); if (i + 128 > len) break; _BRSHA512Compress(buf, x); } memset((uint8_t *)x + (len - i), 0, 128 - (len - i)); // clear remainder of x ((uint8_t *)x)[len - i] = 0x80; // append padding if (len - i >= 112) _BRSHA512Compress(buf, x), memset(x, 0, 128); // length goes to next block x[14] = 0, x[15] = be64((uint64_t)len*8); // append length in bits _BRSHA512Compress(buf, x); // finalize for (i = 0; i < 8; i++) buf[i] = be64(buf[i]); // endian swap memcpy(md64, buf, 64); // write to md mem_clean(x, sizeof(x)); mem_clean(buf, sizeof(buf)); }
// HMAC(key, data) = hash((key xor opad) || hash((key xor ipad) || data)) // opad = 0x5c5c5c...5c5c // ipad = 0x363636...3636 void BRHMAC(void *mac, void (*hash)(void *, const void *, size_t), size_t hashLen, const void *key, size_t keyLen, const void *data, size_t dataLen) { size_t i, blockLen = (hashLen > 32) ? 128 : 64; uint8_t k[hashLen]; uint64_t kipad[(blockLen + dataLen)/sizeof(uint64_t) + 1], kopad[(blockLen + hashLen)/sizeof(uint64_t) + 1]; assert(mac != NULL); assert(hash != NULL); assert(hashLen > 0 && (hashLen % 4) == 0); assert(key != NULL || keyLen == 0); assert(data != NULL || dataLen == 0); if (keyLen > blockLen) hash(k, key, keyLen), key = k, keyLen = sizeof(k); memset(kipad, 0, blockLen); memcpy(kipad, key, keyLen); for (i = 0; i < blockLen/sizeof(uint64_t); i++) kipad[i] ^= 0x3636363636363636; memset(kopad, 0, blockLen); memcpy(kopad, key, keyLen); for (i = 0; i < blockLen/sizeof(uint64_t); i++) kopad[i] ^= 0x5c5c5c5c5c5c5c5c; memcpy(&kipad[blockLen/sizeof(uint64_t)], data, dataLen); hash(&kopad[blockLen/sizeof(uint64_t)], kipad, blockLen + dataLen); hash(mac, kopad, blockLen + hashLen); mem_clean(k, sizeof(k)); mem_clean(kipad, blockLen); mem_clean(kopad, blockLen); }
int cf_ccm_decrypt(const cf_prp *prp, void *prpctx, const uint8_t *cipher, size_t ncipher, size_t L, const uint8_t *header, size_t nheader, const uint8_t *nonce, size_t nnonce, const uint8_t *tag, size_t ntag, uint8_t *plain) { uint8_t block[CF_MAXBLOCK]; assert(ntag >= 4 && ntag <= 16 && ntag % 2 == 0); assert(L >= 2 && L <= 8); assert(nnonce == prp->blocksz - L - 1); uint8_t ctr_nonce[CF_MAXBLOCK]; build_ctr_nonce(ctr_nonce, L, nonce, nnonce); cf_ctr ctr; cf_ctr_init(&ctr, prp, prpctx, ctr_nonce); cf_ctr_custom_counter(&ctr, prp->blocksz - L, L); /* Decrypt tag. */ uint8_t plain_tag[CF_MAXBLOCK]; cf_ctr_cipher(&ctr, tag, plain_tag, ntag); cf_ctr_discard_block(&ctr); /* Decrypt message. */ cf_ctr_cipher(&ctr, cipher, plain, ncipher); cf_cbcmac_stream cm; cf_cbcmac_stream_init(&cm, prp, prpctx); /* Add first block. */ add_block0(&cm, block, prp->blocksz, nonce, nnonce, L, ncipher, nheader, ntag); if (nheader) add_aad(&cm, block, header, nheader); cf_cbcmac_stream_update(&cm, plain, ncipher); zero_pad(&cm); /* Finish tag. */ cf_cbcmac_stream_nopad_final(&cm, block); int err = 0; if (!mem_eq(block, plain_tag, ntag)) { err = 1; mem_clean(plain, ncipher); } mem_clean(block, sizeof block); mem_clean(plain_tag, sizeof plain_tag); return err; }
void cf_cbcmac_stream_reset(cf_cbcmac_stream *ctx) { uint8_t iv_zero[CF_MAXBLOCK] = { 0 }; cf_cbc_init(&ctx->cbc, ctx->prp, ctx->prpctx, iv_zero); mem_clean(ctx->buffer, sizeof ctx->buffer); ctx->used = 0; }
static void _BRSHA256Compress(uint32_t *r, uint32_t *x) { static const uint32_t k[] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; int i; uint32_t a = r[0], b = r[1], c = r[2], d = r[3], e = r[4], f = r[5], g = r[6], h = r[7], t1, t2, w[64]; for (i = 0; i < 16; i++) w[i] = be32(x[i]); for (; i < 64; i++) w[i] = s3(w[i - 2]) + w[i - 7] + s2(w[i - 15]) + w[i - 16]; for (i = 0; i < 64; i++) { t1 = h + s1(e) + ch(e, f, g) + k[i] + w[i]; t2 = s0(a) + maj(a, b, c); h = g, g = f, f = e, e = d + t1, d = c, c = b, b = a, a = t1 + t2; } r[0] += a, r[1] += b, r[2] += c, r[3] += d, r[4] += e, r[5] += f, r[6] += g, r[7] += h; var_clean(&a, &b, &c, &d, &e, &f, &g, &h, &t1, &t2); mem_clean(w, sizeof(w)); }
void cf_hmac_init(cf_hmac_ctx *ctx, const cf_chash *hash, const uint8_t *key, size_t nkey) { assert(ctx); assert(hash); mem_clean(ctx, sizeof *ctx); ctx->hash = hash; /* Prepare key: */ uint8_t k[CF_CHASH_MAXBLK]; /* Shorten long keys. */ if (nkey > hash->blocksz) { cf_hash(hash, key, nkey, k); key = k; nkey = hash->hashsz; } /* Standard doesn't cover case where blocksz < hashsz. */ assert(nkey <= hash->blocksz); /* Right zero-pad short keys. */ if (k != key) memcpy(k, key, nkey); if (hash->blocksz > nkey) memset(k + nkey, 0, hash->blocksz - nkey); /* Start inner hash computation */ uint8_t blk[CF_CHASH_MAXBLK]; xor_b8(blk, k, 0x36, hash->blocksz); hash->init(&ctx->inner); hash->update(&ctx->inner, blk, hash->blocksz); /* And outer. */ xor_b8(blk, k, 0x5c, hash->blocksz); hash->init(&ctx->outer); hash->update(&ctx->outer, blk, hash->blocksz); mem_clean(blk, sizeof blk); mem_clean(k, sizeof k); }
void cf_hash(const cf_chash *h, const void *m, size_t nm, uint8_t *out) { cf_chash_ctx ctx; assert(h); h->init(&ctx); h->update(&ctx, m, nm); h->digest(&ctx, out); mem_clean(&ctx, sizeof ctx); }
void cf_hmac_finish(cf_hmac_ctx *ctx, uint8_t *out) { assert(ctx && ctx->hash); assert(out); uint8_t innerh[CF_MAXHASH]; ctx->hash->digest(&ctx->inner, innerh); ctx->hash->update(&ctx->outer, innerh, ctx->hash->hashsz); ctx->hash->digest(&ctx->outer, out); mem_clean(ctx, sizeof *ctx); }
void cf_cmac_init(cf_cmac *ctx, const cf_prp *prp, void *prpctx) { uint8_t L[CF_MAXBLOCK]; assert(prp->blocksz == 16); mem_clean(ctx, sizeof *ctx); /* L = E_K(0^n) */ mem_clean(L, prp->blocksz); prp->encrypt(prpctx, L, L); /* B = 2L */ cf_gf128 gf; cf_gf128_frombytes_be(L, gf); cf_gf128_double(gf, gf); cf_gf128_tobytes_be(gf, ctx->B); /* P = 4L */ cf_gf128_double(gf, gf); cf_gf128_tobytes_be(gf, ctx->P); ctx->prp = prp; ctx->prpctx = prpctx; }
// sha-1 - not recommended for cryptographic use void BRSHA1(void *md20, const void *data, size_t len) { size_t i; uint32_t x[80], buf[] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 }; // initial buffer values assert(md20 != NULL); assert(data != NULL || len == 0); for (i = 0; i < len; i += 64) { // process data in 64 byte blocks memcpy(x, (const uint8_t *)data + i, (i + 64 < len) ? 64 : len - i); if (i + 64 > len) break; _BRSHA1Compress(buf, x); } memset((uint8_t *)x + (len - i), 0, 64 - (len - i)); // clear remainder of x ((uint8_t *)x)[len - i] = 0x80; // append padding if (len - i >= 56) _BRSHA1Compress(buf, x), memset(x, 0, 64); // length goes to next block x[14] = be32((uint32_t)(len >> 29)), x[15] = be32((uint32_t)(len << 3)); // append length in bits _BRSHA1Compress(buf, x); // finalize for (i = 0; i < 5; i++) buf[i] = be32(buf[i]); // endian swap memcpy(md20, buf, 20); // write to md mem_clean(x, sizeof(x)); mem_clean(buf, sizeof(buf)); }
void BRSHA224(void *md28, const void *data, size_t len) { size_t i; uint32_t x[16], buf[] = { 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 }; // initial buffer values assert(md28 != NULL); assert(data != NULL || len == 0); for (i = 0; i < len; i += 64) { // process data in 64 byte blocks memcpy(x, (const uint8_t *)data + i, (i + 64 < len) ? 64 : len - i); if (i + 64 > len) break; _BRSHA256Compress(buf, x); } memset((uint8_t *)x + (len - i), 0, 64 - (len - i)); // clear remainder of x ((uint8_t *)x)[len - i] = 0x80; // append padding if (len - i >= 56) _BRSHA256Compress(buf, x), memset(x, 0, 64); // length goes to next block x[14] = be32((uint32_t)(len >> 29)), x[15] = be32((uint32_t)(len << 3)); // append length in bits _BRSHA256Compress(buf, x); // finalize for (i = 0; i < 7; i++) buf[i] = be32(buf[i]); // endian swap memcpy(md28, buf, 28); // write to md mem_clean(x, sizeof(x)); mem_clean(buf, sizeof(buf)); }
/* Interesting test case. Divides SIZE into 4 blocks and allocates smalloc each SIZE / 4 block of memory Tests - ability for smalloc to handle adding to an empty allocated_list - ability for smalloc to handle adding to an allocated_list with existing blocks - ability for smalloc to handle when smalloc is called for num_bytes > available size in freelist - ability for freelist to handle when freelist has no memory blocks available - ability for freelist to handle when the size in freelist is equal to the number of bytes called by smalloc (when the last memory block at ptrs[3] is called), and freelist should free this memory block from the list rather than break it into chunks */ int main(void) { mem_init(SIZE); char *ptrs[10]; int i; //Call smalloc 4 times ptrs[0] = smalloc(SIZE * 2); for(i = 0; i <4; i++) { int num_bytes = SIZE / 4; ptrs[i] = smalloc(num_bytes); write_to_mem(num_bytes, ptrs[i], i); } printf("List of allocated blocks:\n"); print_allocated(); printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); printf("freeing %p result = %d\n", ptrs[0], sfree(ptrs[0])); printf("freeing %p result = %d\n", ptrs[1], sfree(ptrs[1])); printf("freeing %p result = %d\n", ptrs[2], sfree(ptrs[2])); printf("freeing %p result = %d\n", ptrs[3], sfree(ptrs[3])); // sfree already called for address at ptrs[1]. Case should be handled printf("freeing %p result = %d\n", ptrs[1], sfree(ptrs[1])); printf("List of allocated blocks:\n"); print_allocated(); printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); mem_clean(); return 0; }
// hmac-drbg with no prediction resistance or additional input // K and V must point to buffers of size hashLen, and ps (personalization string) may be NULL // to generate additional drbg output, use K and V from the previous call, and set seed, nonce and ps to NULL void BRHMACDRBG(void *out, size_t outLen, void *K, void *V, void (*hash)(void *, const void *, size_t), size_t hashLen, const void *seed, size_t seedLen, const void *nonce, size_t nonceLen, const void *ps, size_t psLen) { size_t i, bufLen = hashLen + 1 + seedLen + nonceLen + psLen; uint8_t buf[bufLen]; assert(out != NULL || outLen == 0); assert(K != NULL); assert(V != NULL); assert(hash != NULL); assert(hashLen > 0 && (hashLen % 4) == 0); assert(seed != NULL || seedLen == 0); assert(nonce != NULL || nonceLen == 0); assert(ps != NULL || psLen == 0); if (seed || nonce || ps) { // K = [0x00, 0x00, ... 0x00], V = [0x01, 0x01, ... 0x01] for (i = 0; i < hashLen; i++) ((uint8_t *)K)[i] = 0x00, ((uint8_t *)V)[i] = 0x01; } memcpy(buf, V, hashLen); buf[hashLen] = 0x00; memcpy(&buf[hashLen + 1], seed, seedLen); memcpy(&buf[hashLen + 1 + seedLen], nonce, nonceLen); memcpy(&buf[hashLen + 1 + seedLen + nonceLen], ps, psLen); BRHMAC(K, hash, hashLen, K, hashLen, buf, bufLen); // K = HMAC(K, V || 0x00 || entropy || nonce || ps) BRHMAC(V, hash, hashLen, K, hashLen, V, hashLen); // V = HMAC(K, V) if (seed || nonce || ps) { memcpy(buf, V, hashLen); buf[hashLen] = 0x01; BRHMAC(K, hash, hashLen, K, hashLen, buf, bufLen); // K = HMAC(K, V || 0x01 || entropy || nonce || ps) BRHMAC(V, hash, hashLen, K, hashLen, V, hashLen); // V = HMAC(K, V) } mem_clean(buf, bufLen); for (i = 0; i*hashLen < outLen; i++) { BRHMAC(V, hash, hashLen, K, hashLen, V, hashLen); // V = HMAC(K, V) memcpy((uint8_t *)out + i*hashLen, V, (i*hashLen + hashLen <= outLen) ? hashLen : outLen % hashLen); } }
static void _BRSHA512Compress(uint64_t *r, uint64_t *x) { static const uint64_t k[] = { 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 }; int i; uint64_t a = r[0], b = r[1], c = r[2], d = r[3], e = r[4], f = r[5], g = r[6], h = r[7], t1, t2, w[80]; for (i = 0; i < 16; i++) w[i] = be64(x[i]); for (; i < 80; i++) w[i] = S3(w[i - 2]) + w[i - 7] + S2(w[i - 15]) + w[i - 16]; for (i = 0; i < 80; i++) { t1 = h + S1(e) + ch(e, f, g) + k[i] + w[i]; t2 = S0(a) + maj(a, b, c); h = g, g = f, f = e, e = d + t1, d = c, c = b, b = a, a = t1 + t2; } r[0] += a, r[1] += b, r[2] += c, r[3] += d, r[4] += e, r[5] += f, r[6] += g, r[7] += h; var_clean(&a, &b, &c, &d, &e, &f, &g, &h, &t1, &t2); mem_clean(w, sizeof(w)); }
static int process(const uint8_t key[32], const uint8_t nonce[12], const uint8_t *header, size_t nheader, const uint8_t *input, size_t nbytes, uint8_t *output, int mode, uint8_t tag[16]) { /* First, generate the Poly1305 key by running ChaCha20 with the * given key and a zero counter. The first half of the * 64-byte output is the key. */ uint8_t fullnonce[16] = { 0 }; memcpy(fullnonce + 4, nonce, 12); uint8_t polykey[32] = { 0 }; cf_chacha20_ctx chacha; cf_chacha20_init_custom(&chacha, key, 32, fullnonce, 4); cf_chacha20_cipher(&chacha, polykey, polykey, sizeof polykey); /* Now initialise Poly1305. */ cf_poly1305 poly; cf_poly1305_init(&poly, polykey, polykey + 16); mem_clean(polykey, sizeof polykey); /* Discard next 32 bytes of chacha20 key stream. */ cf_chacha20_cipher(&chacha, polykey, polykey, sizeof polykey); mem_clean(polykey, sizeof polykey); /* The input to Poly1305 is: * AAD || pad(AAD) || cipher || pad(cipher) || len_64(aad) || len_64(cipher) */ uint8_t padbuf[16] = { 0 }; #define PADLEN(x) (16 - ((x) & 0xf)) /* AAD || pad(AAD) */ cf_poly1305_update(&poly, header, nheader); cf_poly1305_update(&poly, padbuf, PADLEN(nheader)); /* || cipher */ if (mode == ENCRYPT) { /* If we're encrypting, we compute the ciphertext * before inputting it into the MAC. */ cf_chacha20_cipher(&chacha, input, output, nbytes); cf_poly1305_update(&poly, output, nbytes); } else { /* Otherwise: decryption -- input the ciphertext. * Delay actual decryption until we checked the MAC. */ cf_poly1305_update(&poly, input, nbytes); } /* || pad(cipher) */ cf_poly1305_update(&poly, padbuf, PADLEN(nbytes)); /* || len_64(aad) || len_64(cipher) */ write64_le(nheader, padbuf); write64_le(nbytes, padbuf + 8); cf_poly1305_update(&poly, padbuf, sizeof padbuf); /* MAC computation is now complete. */ if (mode == ENCRYPT) { cf_poly1305_finish(&poly, tag); mem_clean(&chacha, sizeof chacha); return SUCCESS; } /* Decrypt mode: calculate tag, and check it. * If it's correct, proceed with decryption. */ uint8_t checktag[16]; cf_poly1305_finish(&poly, checktag); if (mem_eq(checktag, tag, sizeof checktag)) { cf_chacha20_cipher(&chacha, input, output, nbytes); mem_clean(&chacha, sizeof chacha); mem_clean(checktag, sizeof checktag); return SUCCESS; } else { mem_clean(output, nbytes); mem_clean(&chacha, sizeof chacha); mem_clean(checktag, sizeof checktag); return FAILURE; } }
/* Test for smalloc and sfree. * Test covers the following scenarios for memory allocation: * - allocation where required size of memory exactly fits free block * - allocation where the first available free block is larger than the required size * resulting in a split. * - multiple allocation that results in consumption of all available memory and * further allocation results in error. * - freeing blocks of memory that are not beside eachother. * - freeing blocks that have a shared edge which results in merge of multiple blocks. * - Reuse of freed merged blocks. * - Releasing all allocated memory. */ int main(void) { mem_init(SIZE); char *ptrs[12]; int i; /* Call smalloc 6 times. */ /* Reference in the comments to individual blocks starts at 1 */ int num_bytes = 10; for(i = 0; i < 6; i++) { ptrs[i] = smalloc(num_bytes); write_to_mem(num_bytes, ptrs[i], i); } /* Should diplay 6 blocks of reserved memory, 10 bytes each in allocated_list*/ printf("List of allocated blocks:\n"); print_allocated(); printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); /* Frees the 2nd and 3rd blocks allocated.*/ printf("freeing %p result = %d\n", ptrs[1], sfree(ptrs[1])); printf("freeing %p result = %d\n", ptrs[2], sfree(ptrs[2])); /* 2nd and 3rd blocks should be removed from allocated_list */ printf("List of allocated blocks:\n"); print_allocated(); /* freelist now should have ONE NEW free block: the result of freeing the 2nd and 3rd block and merging them to produce a free block of size '20 bytes' */ printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); /* Frees the 5th block */ printf("freeing %p result = %d\n", ptrs[4], sfree(ptrs[4])); printf("List of allocated blocks:\n"); print_allocated(); /* ONE new free block (5th - 10 bytes) located in sequence AFTER 2nd-3rd blocks (20 bytes), and BEFORE unused block left over (size = 80 - 60 = 20 bytes)*/ printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); /* Frees the 4th block */ printf("freeing %p result = %d\n", ptrs[3], sfree(ptrs[3])); printf("List of allocated blocks:\n"); print_allocated(); /* 4th block should merge with 2nd-3rd and 5th to produce ONE 40 byte block. */ printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); /* Allocate 7th block with size 35 bytes*/ ptrs[6] = smalloc(35); printf("allocating %p size = %d\n", ptrs[6], 35); write_to_mem(35, ptrs[6], 6); /* For 7th block, 40 byte block of memory freed previously should be reused. Since 40 available bytes > 35 required bytes, 40 block will be SPLIT. The result will be 35 byte block in allocated_list, and 5 byte remainder in freelist.*/ printf("List of allocated blocks:\n"); print_allocated(); printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); /* Allocate 8th block with size 20 bytes*/ ptrs[7] = smalloc(20); printf("allocating %p size = %d\n", ptrs[7], 20); write_to_mem(20, ptrs[7], 7); printf("List of allocated blocks:\n"); print_allocated(); /* freelist should contain only 5 byte block. */ printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); /* Allocate 9th block with size 5 bytes*/ ptrs[8] = smalloc(5); printf("allocating %p size = %d\n", ptrs[8], 5); write_to_mem(5, ptrs[8], 8); printf("List of allocated blocks:\n"); print_allocated(); /* freelist should be empty. */ printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); /* Memory now full*/ /* Allocate 10th block with size 30 bytes*/ ptrs[9] = smalloc(30); printf("allocating for ptrs[9] size = %d. Expected: NULL. Result: %p\n", 30, ptrs[9]); /* Allocate 11th block with size 1 byte*/ ptrs[10] = smalloc(1); printf("allocating for ptrs[10] size = %d. Expected: NULL. Result: %p\n", 1, ptrs[10]); /* Unchanged */ printf("List of allocated blocks:\n"); print_allocated(); printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); /* Free all. Expected: no crash */ for (i = 0; i < 11; i++){ printf("freeing ptrs[%d] %p, result = %d\n", i, ptrs[i], sfree(ptrs[i])); } /* Restart: 1 free block of 80 total SIZE bytes*/ printf("List of allocated blocks:\n"); print_allocated(); printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); /* Clean all */ printf("Cleaning memory\n"); mem_clean(); /* Each print-out should be blank.*/ printf("List of allocated blocks:\n"); print_allocated(); printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); return 0; }
/* Simple test for malloc and free. We will want a proper test driver */ int main(int argc, char **argv) { int opt; int pr = 0; struct sigaction newact; /* fill in newact */ newact.sa_handler = handle_seg; newact.sa_flags = 0; sigaction(SIGSEGV, &newact, NULL); while ((opt = getopt(argc, argv, "p")) != -1) { switch (opt) { case 'p': pr = 1; break; default: /* '?' */ fprintf(stderr, "Usage: %s [-p ] tracefile\n", argv[0]); exit(EXIT_FAILURE); } } if(optind >= argc) { fprintf(stderr, "Usage: %s [-p ] tracefile\n", argv[0]); exit(EXIT_FAILURE); } char *tracefile = argv[optind]; mem_init(SIZE); char *ptrs[MAXOPS]; int i; /* Call my malloc 4 times */ //ptrs[i] = smalloc(num_bytes); //write_to_mem(num_bytes, ptrs[i], i); FILE *fp = fopen(tracefile, "r"); if(!fp) { fprintf(stderr, "Usage: driver [-p] <tracefile>\n"); exit(1); } load_trace(fp); fclose(fp); for(i = 0; i < num_ops; i++) { switch(trace[i].type) { case 'm': ptrs[trace[i].index] = smalloc(trace[i].size); if(pr) { printf("smalloc block %d addr %p size %d\n", trace[i].index, ptrs[trace[i].index], trace[i].size); } if(!ptrs[trace[i].index]) { fprintf(stderr, "Error: smalloc returned NULL index=%d, size=%d\n", trace[i].index, trace[i].size); } // check for valid pointer if((ptrs[trace[i].index] < (char *)mem) || (ptrs[trace[i].index] + trace[i].size) > ((char *)mem + SIZE)) { fprintf(stderr, "Error: malloc block %d addr %p size %d heap overflow\n", trace[i].index, ptrs[trace[i].index], trace[i].size); } else { write_to_mem(trace[i].size, ptrs[trace[i].index],trace[i].index); } break; case 'f': if(pr) { printf("sfree block %d addr %p\n", trace[i].index, ptrs[trace[i].index]); } if(sfree(ptrs[trace[i].index])) { fprintf(stderr, "Error: free block %d addr %p\n", trace[i].index, ptrs[trace[i].index]); } break; default : fprintf(stderr, "ERROR: bad type of instruction %c for block %d\n", trace[i].type, trace[i].index); } } if(pr) { printf("Total free mem: %d\n", total_space(freelist)); printf("Total allocated mem: %d\n", total_space(allocated_list)); printf("List of allocated blocks:\n"); print_allocated(); printf("List of free blocks:\n"); print_free(); printf("Contents of allocated memory:\n"); print_mem(); } else { printf("Total free mem: %d\n", total_space(freelist)); printf("Total allocated mem: %d\n", total_space(allocated_list)); printf("Number of allocated blocks: %d\n", num_blocks(allocated_list)); } mem_clean(); return 0; }