* commit 'ab2ad8bd56882c0ea160b154e8b836eb71abc49d': lavf: Add functions for SRTP decryption/encryption lavu: Add an API for calculating HMAC (RFC 2104) Conflicts: doc/APIchanges libavutil/version.h
Unified · Split
| @@ -132,6 +132,9 @@ API changes, most recent first: · 131 unmodified lines | ||
| 132 | 132 | 2012-03-26 - a67d9cf - lavfi 2.66.100 |
| 133 | 133 | Add avfilter_fill_frame_from_{audio_,}buffer_ref() functions. |
| 134 | 134 | |
| 135 | +2013-01-xx - xxxxxxx - lavu 52.5.0 - hmac.h | |
| 136 | + Add AVHMAC. | |
| 137 | + | |
| 135 | 138 | 2013-01-13 - xxxxxxx - lavc 54.36.0 - vdpau.h |
| 136 | 139 | Add AVVDPAUContext struct for VDPAU hardware-accelerated decoding. |
| 137 | 140 | |
| @@ -0,0 +1,293 @@ | ||
| 1 | +/* | |
| 2 | + * SRTP encryption/decryption | |
| 3 | + * Copyright (c) 2012 Martin Storsjo | |
| 4 | + * | |
| 5 | + * This file is part of FFmpeg. | |
| 6 | + * | |
| 7 | + * FFmpeg is free software; you can redistribute it and/or | |
| 8 | + * modify it under the terms of the GNU Lesser General Public | |
| 9 | + * License as published by the Free Software Foundation; either | |
| 10 | + * version 2.1 of the License, or (at your option) any later version. | |
| 11 | + * | |
| 12 | + * FFmpeg is distributed in the hope that it will be useful, | |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 15 | + * Lesser General Public License for more details. | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU Lesser General Public | |
| 18 | + * License along with FFmpeg; if not, write to the Free Software | |
| 19 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 | + */ | |
| 21 | + | |
| 22 | +#include "libavutil/base64.h" | |
| 23 | +#include "libavutil/aes.h" | |
| 24 | +#include "libavutil/hmac.h" | |
| 25 | +#include "libavutil/intreadwrite.h" | |
| 26 | +#include "libavutil/log.h" | |
| 27 | +#include "rtp.h" | |
| 28 | +#include "srtp.h" | |
| 29 | + | |
| 30 | +void ff_srtp_free(struct SRTPContext *s) | |
| 31 | +{ | |
| 32 | + if (!s) | |
| 33 | + return; | |
| 34 | + av_freep(&s->aes); | |
| 35 | + if (s->hmac) | |
| 36 | + av_hmac_free(s->hmac); | |
| 37 | + s->hmac = NULL; | |
| 38 | +} | |
| 39 | + | |
| 40 | +static void encrypt_counter(struct AVAES *aes, uint8_t *iv, uint8_t *outbuf, | |
| 41 | + int outlen) | |
| 42 | +{ | |
| 43 | + int i, j, outpos; | |
| 44 | + for (i = 0, outpos = 0; outpos < outlen; i++) { | |
| 45 | + uint8_t keystream[16]; | |
| 46 | + AV_WB16(&iv[14], i); | |
| 47 | + av_aes_crypt(aes, keystream, iv, 1, NULL, 0); | |
| 48 | + for (j = 0; j < 16 && outpos < outlen; j++, outpos++) | |
| 49 | + outbuf[outpos] ^= keystream[j]; | |
| 50 | + } | |
| 51 | +} | |
| 52 | + | |
| 53 | +static void derive_key(struct AVAES *aes, const uint8_t *salt, int label, | |
| 54 | + uint8_t *out, int outlen) | |
| 55 | +{ | |
| 56 | + uint8_t input[16] = { 0 }; | |
| 57 | + memcpy(input, salt, 14); | |
| 58 | + // Key derivation rate assumed to be zero | |
| 59 | + input[14 - 7] ^= label; | |
| 60 | + memset(out, 0, outlen); | |
| 61 | + encrypt_counter(aes, input, out, outlen); | |
| 62 | +} | |
| 63 | + | |
| 64 | +int ff_srtp_set_crypto(struct SRTPContext *s, const char *suite, | |
| 65 | + const char *params) | |
| 66 | +{ | |
| 67 | + uint8_t buf[30]; | |
| 68 | + | |
| 69 | + ff_srtp_free(s); | |
| 70 | + | |
| 71 | + // RFC 4568 | |
| 72 | + if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_80")) { | |
| 73 | + s->hmac_size = 10; | |
| 74 | + } else if (!strcmp(suite, "AES_CM_128_HMAC_SHA1_32")) { | |
| 75 | + s->hmac_size = 4; | |
| 76 | + } else { | |
| 77 | + av_log(NULL, AV_LOG_WARNING, "SRTP Crypto suite %s not supported\n", | |
| 78 | + suite); | |
| 79 | + return AVERROR(EINVAL); | |
| 80 | + } | |
| 81 | + if (av_base64_decode(buf, params, sizeof(buf)) != sizeof(buf)) { | |
| 82 | + av_log(NULL, AV_LOG_WARNING, "Incorrect amount of SRTP params\n"); | |
| 83 | + return AVERROR(EINVAL); | |
| 84 | + } | |
| 85 | + // MKI and lifetime not handled yet | |
| 86 | + s->aes = av_aes_alloc(); | |
| 87 | + s->hmac = av_hmac_alloc(AV_HMAC_SHA1); | |
| 88 | + if (!s->aes || !s->hmac) | |
| 89 | + return AVERROR(ENOMEM); | |
| 90 | + memcpy(s->master_key, buf, 16); | |
| 91 | + memcpy(s->master_salt, buf + 16, 14); | |
| 92 | + | |
| 93 | + // RFC 3711 | |
| 94 | + av_aes_init(s->aes, s->master_key, 128, 0); | |
| 95 | + | |
| 96 | + derive_key(s->aes, s->master_salt, 0x00, s->rtp_key, sizeof(s->rtp_key)); | |
| 97 | + derive_key(s->aes, s->master_salt, 0x02, s->rtp_salt, sizeof(s->rtp_salt)); | |
| 98 | + derive_key(s->aes, s->master_salt, 0x01, s->rtp_auth, sizeof(s->rtp_auth)); | |
| 99 | + | |
| 100 | + derive_key(s->aes, s->master_salt, 0x03, s->rtcp_key, sizeof(s->rtcp_key)); | |
| 101 | + derive_key(s->aes, s->master_salt, 0x05, s->rtcp_salt, sizeof(s->rtcp_salt)); | |
| 102 | + derive_key(s->aes, s->master_salt, 0x04, s->rtcp_auth, sizeof(s->rtcp_auth)); | |
| 103 | + return 0; | |
| 104 | +} | |
| 105 | + | |
| 106 | +static void create_iv(uint8_t *iv, const uint8_t *salt, uint64_t index, | |
| 107 | + uint32_t ssrc) | |
| 108 | +{ | |
| 109 | + uint8_t indexbuf[8]; | |
| 110 | + int i; | |
| 111 | + memset(iv, 0, 16); | |
| 112 | + AV_WB32(&iv[4], ssrc); | |
| 113 | + AV_WB64(indexbuf, index); | |
| 114 | + for (i = 0; i < 8; i++) // index << 16 | |
| 115 | + iv[6 + i] ^= indexbuf[i]; | |
| 116 | + for (i = 0; i < 14; i++) | |
| 117 | + iv[i] ^= salt[i]; | |
| 118 | +} | |
| 119 | + | |
| 120 | +int ff_srtp_decrypt(struct SRTPContext *s, uint8_t *buf, int *lenptr) | |
| 121 | +{ | |
| 122 | + uint8_t iv[16] = { 0 }, hmac[20]; | |
| 123 | + int len = *lenptr; | |
| 124 | + int ext, seq_largest; | |
| 125 | + uint32_t ssrc, roc; | |
| 126 | + uint64_t index; | |
| 127 | + int rtcp; | |
| 128 | + | |
| 129 | + // TODO: Missing replay protection | |
| 130 | + | |
| 131 | + if (len < s->hmac_size) | |
| 132 | + return AVERROR_INVALIDDATA; | |
| 133 | + | |
| 134 | + rtcp = RTP_PT_IS_RTCP(buf[1]); | |
| 135 | + | |
| 136 | + // Authentication HMAC | |
| 137 | + av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth)); | |
| 138 | + // If MKI is used, this should exclude the MKI as well | |
| 139 | + av_hmac_update(s->hmac, buf, len - s->hmac_size); | |
| 140 | + | |
| 141 | + if (!rtcp) { | |
| 142 | + int seq = AV_RB16(buf + 2); | |
| 143 | + uint32_t v; | |
| 144 | + uint8_t rocbuf[4]; | |
| 145 | + | |
| 146 | + // RFC 3711 section 3.3.1, appendix A | |
| 147 | + seq_largest = s->seq_initialized ? s->seq_largest : seq; | |
| 148 | + v = roc = s->roc; | |
| 149 | + if (seq_largest < 32768) { | |
| 150 | + if (seq - seq_largest > 32768) | |
| 151 | + v = roc - 1; | |
| 152 | + } else { | |
| 153 | + if (seq_largest - 32768 > seq) | |
| 154 | + v = roc + 1; | |
| 155 | + } | |
| 156 | + if (v == roc) { | |
| 157 | + seq_largest = FFMAX(seq_largest, seq); | |
| 158 | + } else if (v == roc + 1) { | |
| 159 | + seq_largest = seq; | |
| 160 | + roc = v; | |
| 161 | + } | |
| 162 | + index = seq + (((uint64_t)v) << 16); | |
| 163 | + | |
| 164 | + AV_WB32(rocbuf, roc); | |
| 165 | + av_hmac_update(s->hmac, rocbuf, 4); | |
| 166 | + } | |
| 167 | + | |
| 168 | + av_hmac_final(s->hmac, hmac, sizeof(hmac)); | |
| 169 | + if (memcmp(hmac, buf + len - s->hmac_size, s->hmac_size)) { | |
| 170 | + av_log(NULL, AV_LOG_WARNING, "HMAC mismatch\n"); | |
| 171 | + return AVERROR_INVALIDDATA; | |
| 172 | + } | |
| 173 | + | |
| 174 | + len -= s->hmac_size; | |
| 175 | + *lenptr = len; | |
| 176 | + | |
| 177 | + if (len < 12) | |
| 178 | + return AVERROR_INVALIDDATA; | |
| 179 | + | |
| 180 | + if (rtcp) { | |
| 181 | + uint32_t srtcp_index = AV_RB32(buf + len - 4); | |
| 182 | + len -= 4; | |
| 183 | + *lenptr = len; | |
| 184 | + | |
| 185 | + ssrc = AV_RB32(buf + 4); | |
| 186 | + index = srtcp_index & 0x7fffffff; | |
| 187 | + | |
| 188 | + buf += 8; | |
| 189 | + len -= 8; | |
| 190 | + if (!(srtcp_index & 0x80000000)) | |
| 191 | + return 0; | |
| 192 | + } else { | |
| 193 | + s->seq_initialized = 1; | |
| 194 | + s->seq_largest = seq_largest; | |
| 195 | + s->roc = roc; | |
| 196 | + | |
| 197 | + ext = buf[0] & 0x10; | |
| 198 | + ssrc = AV_RB32(buf + 8); | |
| 199 | + | |
| 200 | + buf += 12; | |
| 201 | + len -= 12; | |
| 202 | + | |
| 203 | + if (ext) { | |
| 204 | + if (len < 4) | |
| 205 | + return AVERROR_INVALIDDATA; | |
| 206 | + ext = (AV_RB16(buf + 2) + 1) * 4; | |
| 207 | + if (len < ext) | |
| 208 | + return AVERROR_INVALIDDATA; | |
| 209 | + len -= ext; | |
| 210 | + buf += ext; | |
| 211 | + } | |
| 212 | + } | |
| 213 | + | |
| 214 | + create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc); | |
| 215 | + av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, 128, 0); | |
| 216 | + encrypt_counter(s->aes, iv, buf, len); | |
| 217 | + | |
| 218 | + return 0; | |
| 219 | +} | |
| 220 | + | |
| 221 | +int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len, | |
| 222 | + uint8_t *out, int outlen) | |
| 223 | +{ | |
| 224 | + uint8_t iv[16] = { 0 }, hmac[20]; | |
| 225 | + uint64_t index; | |
| 226 | + uint32_t ssrc; | |
| 227 | + int rtcp; | |
| 228 | + uint8_t *buf; | |
| 229 | + | |
| 230 | + if (len + 14 > outlen) | |
| 231 | + return 0; | |
| 232 | + if (len < 12) | |
| 233 | + return 0; | |
| 234 | + | |
| 235 | + memcpy(out, in, len); | |
| 236 | + buf = out; | |
| 237 | + | |
| 238 | + rtcp = RTP_PT_IS_RTCP(buf[1]); | |
| 239 | + | |
| 240 | + if (rtcp) { | |
| 241 | + ssrc = AV_RB32(buf + 4); | |
| 242 | + index = s->rtcp_index++; | |
| 243 | + | |
| 244 | + buf += 8; | |
| 245 | + len -= 8; | |
| 246 | + } else { | |
| 247 | + int ext; | |
| 248 | + int seq = AV_RB16(buf + 2); | |
| 249 | + ssrc = AV_RB32(buf + 8); | |
| 250 | + | |
| 251 | + if (seq < s->seq_largest) | |
| 252 | + s->roc++; | |
| 253 | + s->seq_largest = seq; | |
| 254 | + index = seq + (((uint64_t)s->roc) << 16); | |
| 255 | + | |
| 256 | + ext = buf[0] & 0x10; | |
| 257 | + | |
| 258 | + buf += 12; | |
| 259 | + len -= 12; | |
| 260 | + | |
| 261 | + if (ext) { | |
| 262 | + if (len < 4) | |
| 263 | + return AVERROR_INVALIDDATA; | |
| 264 | + ext = (AV_RB16(buf + 2) + 1) * 4; | |
| 265 | + if (len < ext) | |
| 266 | + return AVERROR_INVALIDDATA; | |
| 267 | + len -= ext; | |
| 268 | + buf += ext; | |
| 269 | + } | |
| 270 | + } | |
| 271 | + | |
| 272 | + create_iv(iv, rtcp ? s->rtcp_salt : s->rtp_salt, index, ssrc); | |
| 273 | + av_aes_init(s->aes, rtcp ? s->rtcp_key : s->rtp_key, 128, 0); | |
| 274 | + encrypt_counter(s->aes, iv, buf, len); | |
| 275 | + | |
| 276 | + if (rtcp) { | |
| 277 | + AV_WB32(buf + len, 0x80000000 | index); | |
| 278 | + len += 4; | |
| 279 | + } | |
| 280 | + | |
| 281 | + av_hmac_init(s->hmac, rtcp ? s->rtcp_auth : s->rtp_auth, sizeof(s->rtp_auth)); | |
| 282 | + av_hmac_update(s->hmac, out, buf + len - out); | |
| 283 | + if (!rtcp) { | |
| 284 | + uint8_t rocbuf[4]; | |
| 285 | + AV_WB32(rocbuf, s->roc); | |
| 286 | + av_hmac_update(s->hmac, rocbuf, 4); | |
| 287 | + } | |
| 288 | + av_hmac_final(s->hmac, hmac, sizeof(hmac)); | |
| 289 | + | |
| 290 | + memcpy(buf + len, hmac, s->hmac_size); | |
| 291 | + len += s->hmac_size; | |
| 292 | + return buf + len - out; | |
| 293 | +} | |
| @@ -0,0 +1,52 @@ | ||
| 1 | +/* | |
| 2 | + * SRTP encryption/decryption | |
| 3 | + * Copyright (c) 2012 Martin Storsjo | |
| 4 | + * | |
| 5 | + * This file is part of FFmpeg. | |
| 6 | + * | |
| 7 | + * FFmpeg is free software; you can redistribute it and/or | |
| 8 | + * modify it under the terms of the GNU Lesser General Public | |
| 9 | + * License as published by the Free Software Foundation; either | |
| 10 | + * version 2.1 of the License, or (at your option) any later version. | |
| 11 | + * | |
| 12 | + * FFmpeg is distributed in the hope that it will be useful, | |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 15 | + * Lesser General Public License for more details. | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU Lesser General Public | |
| 18 | + * License along with FFmpeg; if not, write to the Free Software | |
| 19 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 | + */ | |
| 21 | + | |
| 22 | +#ifndef AVFORMAT_SRTP_H | |
| 23 | +#define AVFORMAT_SRTP_H | |
| 24 | + | |
| 25 | +#include <stdint.h> | |
| 26 | + | |
| 27 | +struct AVAES; | |
| 28 | +struct AVHMAC; | |
| 29 | + | |
| 30 | +struct SRTPContext { | |
| 31 | + struct AVAES *aes; | |
| 32 | + struct AVHMAC *hmac; | |
| 33 | + int hmac_size; | |
| 34 | + uint8_t master_key[16]; | |
| 35 | + uint8_t master_salt[14]; | |
| 36 | + uint8_t rtp_key[16], rtcp_key[16]; | |
| 37 | + uint8_t rtp_salt[14], rtcp_salt[14]; | |
| 38 | + uint8_t rtp_auth[20], rtcp_auth[20]; | |
| 39 | + int seq_largest, seq_initialized; | |
| 40 | + uint32_t roc; | |
| 41 | + | |
| 42 | + uint32_t rtcp_index; | |
| 43 | +}; | |
| 44 | + | |
| 45 | +int ff_srtp_set_crypto(struct SRTPContext *s, const char *suite, | |
| 46 | + const char *params); | |
| 47 | +void ff_srtp_free(struct SRTPContext *s); | |
| 48 | +int ff_srtp_decrypt(struct SRTPContext *s, uint8_t *buf, int *lenptr); | |
| 49 | +int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len, | |
| 50 | + uint8_t *out, int outlen); | |
| 51 | + | |
| 52 | +#endif /* AVFORMAT_SRTP_H */ | |
| @@ -22,6 +22,7 @@ HEADERS = adler32.h \ · 21 unmodified lines | ||
| 22 | 22 | eval.h \ |
| 23 | 23 | fifo.h \ |
| 24 | 24 | file.h \ |
| 25 | + hmac.h \ | |
| 25 | 26 | imgutils.h \ |
| 26 | 27 | intfloat.h \ |
| 27 | 28 | intfloat_readwrite.h \ |
| @@ -72,6 +73,7 @@ OBJS = adler32.o \ · 44 unmodified lines | ||
| 72 | 73 | fifo.o \ |
| 73 | 74 | file.o \ |
| 74 | 75 | float_dsp.o \ |
| 76 | + hmac.o \ | |
| 75 | 77 | imgutils.o \ |
| 76 | 78 | intfloat_readwrite.o \ |
| 77 | 79 | intmath.o \ |
| @@ -0,0 +1,138 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2012 Martin Storsjo | |
| 3 | + * | |
| 4 | + * This file is part of FFmpeg. | |
| 5 | + * | |
| 6 | + * FFmpeg is free software; you can redistribute it and/or | |
| 7 | + * modify it under the terms of the GNU Lesser General Public | |
| 8 | + * License as published by the Free Software Foundation; either | |
| 9 | + * version 2.1 of the License, or (at your option) any later version. | |
| 10 | + * | |
| 11 | + * FFmpeg is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 14 | + * Lesser General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU Lesser General Public | |
| 17 | + * License along with FFmpeg; if not, write to the Free Software | |
| 18 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 19 | + */ | |
| 20 | + | |
| 21 | +#include <string.h> | |
| 22 | + | |
| 23 | +#include "hmac.h" | |
| 24 | +#include "md5.h" | |
| 25 | +#include "sha.h" | |
| 26 | +#include "mem.h" | |
| 27 | + | |
| 28 | +#define MAX_HASHLEN 20 | |
| 29 | +#define MAX_BLOCKLEN 64 | |
| 30 | + | |
| 31 | +struct AVHMAC { | |
| 32 | + void *hash; | |
| 33 | + int blocklen, hashlen; | |
| 34 | + void (*final)(void*, uint8_t*); | |
| 35 | + void (*update)(void*, const uint8_t*, int len); | |
| 36 | + void (*init)(void*); | |
| 37 | + uint8_t key[MAX_BLOCKLEN]; | |
| 38 | + int keylen; | |
| 39 | +}; | |
| 40 | + | |
| 41 | +static void sha1_init(void *ctx) | |
| 42 | +{ | |
| 43 | + av_sha_init(ctx, 160); | |
| 44 | +} | |
| 45 | + | |
| 46 | +AVHMAC *av_hmac_alloc(enum AVHMACType type) | |
| 47 | +{ | |
| 48 | + AVHMAC *c = av_mallocz(sizeof(*c)); | |
| 49 | + if (!c) | |
| 50 | + return NULL; | |
| 51 | + switch (type) { | |
| 52 | + case AV_HMAC_MD5: | |
| 53 | + c->blocklen = 64; | |
| 54 | + c->hashlen = 16; | |
| 55 | + c->init = av_md5_init; | |
| 56 | + c->update = av_md5_update; | |
| 57 | + c->final = av_md5_final; | |
| 58 | + c->hash = av_md5_alloc(); | |
| 59 | + break; | |
| 60 | + case AV_HMAC_SHA1: | |
| 61 | + c->blocklen = 64; | |
| 62 | + c->hashlen = 20; | |
| 63 | + c->init = sha1_init; | |
| 64 | + c->update = av_sha_update; | |
| 65 | + c->final = av_sha_final; | |
| 66 | + c->hash = av_sha_alloc(); | |
| 67 | + break; | |
| 68 | + default: | |
| 69 | + av_free(c); | |
| 70 | + return NULL; | |
| 71 | + } | |
| 72 | + if (!c->hash) { | |
| 73 | + av_free(c); | |
| 74 | + return NULL; | |
| 75 | + } | |
| 76 | + return c; | |
| 77 | +} | |
| 78 | + | |
| 79 | +void av_hmac_free(AVHMAC *c) | |
| 80 | +{ | |
| 81 | + if (!c) | |
| 82 | + return; | |
| 83 | + av_free(c->hash); | |
| 84 | + av_free(c); | |
| 85 | +} | |
| 86 | + | |
| 87 | +void av_hmac_init(AVHMAC *c, const uint8_t *key, unsigned int keylen) | |
| 88 | +{ | |
| 89 | + int i; | |
| 90 | + uint8_t block[MAX_BLOCKLEN]; | |
| 91 | + if (keylen > c->blocklen) { | |
| 92 | + c->init(c->hash); | |
| 93 | + c->update(c->hash, key, keylen); | |
| 94 | + c->final(c->hash, c->key); | |
| 95 | + c->keylen = c->hashlen; | |
| 96 | + } else { | |
| 97 | + memcpy(c->key, key, keylen); | |
| 98 | + c->keylen = keylen; | |
| 99 | + } | |
| 100 | + c->init(c->hash); | |
| 101 | + for (i = 0; i < c->keylen; i++) | |
| 102 | + block[i] = c->key[i] ^ 0x36; | |
| 103 | + for (i = c->keylen; i < c->blocklen; i++) | |
| 104 | + block[i] = 0x36; | |
| 105 | + c->update(c->hash, block, c->blocklen); | |
| 106 | +} | |
| 107 | + | |
| 108 | +void av_hmac_update(AVHMAC *c, const uint8_t *data, unsigned int len) | |
| 109 | +{ | |
| 110 | + c->update(c->hash, data, len); | |
| 111 | +} | |
| 112 | + | |
| 113 | +int av_hmac_final(AVHMAC *c, uint8_t *out, unsigned int outlen) | |
| 114 | +{ | |
| 115 | + uint8_t block[MAX_BLOCKLEN]; | |
| 116 | + int i; | |
| 117 | + if (outlen < c->hashlen) | |
| 118 | + return AVERROR(EINVAL); | |
| 119 | + c->final(c->hash, out); | |
| 120 | + c->init(c->hash); | |
| 121 | + for (i = 0; i < c->keylen; i++) | |
| 122 | + block[i] = c->key[i] ^ 0x5C; | |
| 123 | + for (i = c->keylen; i < c->blocklen; i++) | |
| 124 | + block[i] = 0x5C; | |
| 125 | + c->update(c->hash, block, c->blocklen); | |
| 126 | + c->update(c->hash, out, c->hashlen); | |
| 127 | + c->final(c->hash, out); | |
| 128 | + return c->hashlen; | |
| 129 | +} | |
| 130 | + | |
| 131 | +int av_hmac_calc(AVHMAC *c, const uint8_t *data, unsigned int len, | |
| 132 | + const uint8_t *key, unsigned int keylen, | |
| 133 | + uint8_t *out, unsigned int outlen) | |
| 134 | +{ | |
| 135 | + av_hmac_init(c, key, keylen); | |
| 136 | + av_hmac_update(c, data, len); | |
| 137 | + return av_hmac_final(c, out, outlen); | |
| 138 | +} | |
| @@ -0,0 +1,95 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2012 Martin Storsjo | |
| 3 | + * | |
| 4 | + * This file is part of FFmpeg. | |
| 5 | + * | |
| 6 | + * FFmpeg is free software; you can redistribute it and/or | |
| 7 | + * modify it under the terms of the GNU Lesser General Public | |
| 8 | + * License as published by the Free Software Foundation; either | |
| 9 | + * version 2.1 of the License, or (at your option) any later version. | |
| 10 | + * | |
| 11 | + * FFmpeg is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 14 | + * Lesser General Public License for more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU Lesser General Public | |
| 17 | + * License along with FFmpeg; if not, write to the Free Software | |
| 18 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 19 | + */ | |
| 20 | + | |
| 21 | +#ifndef AVUTIL_HMAC_H | |
| 22 | +#define AVUTIL_HMAC_H | |
| 23 | + | |
| 24 | +#include <stdint.h> | |
| 25 | + | |
| 26 | +/** | |
| 27 | + * @defgroup lavu_hmac HMAC | |
| 28 | + * @ingroup lavu_crypto | |
| 29 | + * @{ | |
| 30 | + */ | |
| 31 | + | |
| 32 | +enum AVHMACType { | |
| 33 | + AV_HMAC_MD5, | |
| 34 | + AV_HMAC_SHA1, | |
| 35 | +}; | |
| 36 | + | |
| 37 | +typedef struct AVHMAC AVHMAC; | |
| 38 | + | |
| 39 | +/** | |
| 40 | + * Allocate an AVHMAC context. | |
| 41 | + * @param type The hash function used for the HMAC. | |
| 42 | + */ | |
| 43 | +AVHMAC *av_hmac_alloc(enum AVHMACType type); | |
| 44 | + | |
| 45 | +/** | |
| 46 | + * Free an AVHMAC context. | |
| 47 | + * @param ctx The context to free, may be NULL | |
| 48 | + */ | |
| 49 | +void av_hmac_free(AVHMAC *ctx); | |
| 50 | + | |
| 51 | +/** | |
| 52 | + * Initialize an AVHMAC context with an authentication key. | |
| 53 | + * @param ctx The HMAC context | |
| 54 | + * @param key The authentication key | |
| 55 | + * @param keylen The length of the key, in bytes | |
| 56 | + */ | |
| 57 | +void av_hmac_init(AVHMAC *ctx, const uint8_t *key, unsigned int keylen); | |
| 58 | + | |
| 59 | +/** | |
| 60 | + * Hash data with the HMAC. | |
| 61 | + * @param ctx The HMAC context | |
| 62 | + * @param data The data to hash | |
| 63 | + * @param len The length of the data, in bytes | |
| 64 | + */ | |
| 65 | +void av_hmac_update(AVHMAC *ctx, const uint8_t *data, unsigned int len); | |
| 66 | + | |
| 67 | +/** | |
| 68 | + * Finish hashing and output the HMAC digest. | |
| 69 | + * @param ctx The HMAC context | |
| 70 | + * @param out The output buffer to write the digest into | |
| 71 | + * @param outlen The length of the out buffer, in bytes | |
| 72 | + * @return The number of bytes written to out, or a negative error code. | |
| 73 | + */ | |
| 74 | +int av_hmac_final(AVHMAC *ctx, uint8_t *out, unsigned int outlen); | |
| 75 | + | |
| 76 | +/** | |
| 77 | + * Hash an array of data with a key. | |
| 78 | + * @param ctx The HMAC context | |
| 79 | + * @param data The data to hash | |
| 80 | + * @param len The length of the data, in bytes | |
| 81 | + * @param key The authentication key | |
| 82 | + * @param keylen The length of the key, in bytes | |
| 83 | + * @param out The output buffer to write the digest into | |
| 84 | + * @param outlen The length of the out buffer, in bytes | |
| 85 | + * @return The number of bytes written to out, or a negative error code. | |
| 86 | + */ | |
| 87 | +int av_hmac_calc(AVHMAC *ctx, const uint8_t *data, unsigned int len, | |
| 88 | + const uint8_t *key, unsigned int keylen, | |
| 89 | + uint8_t *out, unsigned int outlen); | |
| 90 | + | |
| 91 | +/** | |
| 92 | + * @} | |
| 93 | + */ | |
| 94 | + | |
| 95 | +#endif /* AVUTIL_HMAC_H */ | |
| @@ -75,7 +75,7 @@ · 74 unmodified lines | ||
| 75 | 75 | */ |
| 76 | 76 | |
| 77 | 77 | #define LIBAVUTIL_VERSION_MAJOR 52 |
| 78 | −#define LIBAVUTIL_VERSION_MINOR 14 | |
| 78 | +#define LIBAVUTIL_VERSION_MINOR 15 | |
| 79 | 79 | #define LIBAVUTIL_VERSION_MICRO 100 |
| 80 | 80 | |
| 81 | 81 | #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ |