static int comp_init(struct comp *c, unsigned offs, const uint8_t *key, size_t key_b, const uint8_t *s, size_t s_b, size_t tag_len, bool encrypted) { uint8_t k_e[MAX_KEYLEN], k_a[SHA_DIGEST_LENGTH]; int err = 0; if (key_b > sizeof(k_e)) return EINVAL; if (tag_len > SHA_DIGEST_LENGTH) return EINVAL; c->tag_len = tag_len; err |= srtp_derive(k_e, key_b, 0x00+offs, key, key_b, s, s_b); err |= srtp_derive(k_a, sizeof(k_a), 0x01+offs, key, key_b, s, s_b); err |= srtp_derive(c->k_s.u8, 14, 0x02+offs, key, key_b, s, s_b); if (err) return err; if (encrypted) { err = aes_alloc(&c->aes, AES_MODE_CTR, k_e, key_b*8, NULL); if (err) return err; } err = hmac_create(&c->hmac, HMAC_HASH_SHA1, k_a, sizeof(k_a)); if (err) return err; return err; }
int srtp_derive(uint8_t *out, size_t out_len, uint8_t label, const uint8_t *master_key, size_t key_bytes, const uint8_t *master_salt, size_t salt_bytes) { uint8_t x[AES_BLOCK_SIZE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static const uint8_t null[AES_BLOCK_SIZE * 2]; struct aes *aes; int err; if (!out || !master_key || !master_salt) return EINVAL; if (out_len > sizeof(null) || salt_bytes > sizeof(x)) return EINVAL; memcpy(x, master_salt, salt_bytes); x[7] ^= label; /* NOTE: Counter Mode is used for both CTR and GCM */ err = aes_alloc(&aes, AES_MODE_CTR, master_key, key_bytes*8, x); if (err) return err; err = aes_encr(aes, out, null, out_len); mem_deref(aes); return err; }