* 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 | 2012-03-26 - a67d9cf - lavfi 2.66.100 | 132 | 2012-03-26 - a67d9cf - lavfi 2.66.100 |
| 133 | Add avfilter_fill_frame_from_{audio_,}buffer_ref() functions. | 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 | 2013-01-13 - xxxxxxx - lavc 54.36.0 - vdpau.h | 138 | 2013-01-13 - xxxxxxx - lavc 54.36.0 - vdpau.h |
| 136 | Add AVVDPAUContext struct for VDPAU hardware-accelerated decoding. | 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 | eval.h \ | 22 | eval.h \ |
| 23 | fifo.h \ | 23 | fifo.h \ |
| 24 | file.h \ | 24 | file.h \ |
| 25 | hmac.h \ | ||
| 25 | imgutils.h \ | 26 | imgutils.h \ |
| 26 | intfloat.h \ | 27 | intfloat.h \ |
| 27 | intfloat_readwrite.h \ | 28 | intfloat_readwrite.h \ |
| @@ -72,6 +73,7 @@ OBJS = adler32.o \ · 44 unmodified lines | |||
| 72 | fifo.o \ | 73 | fifo.o \ |
| 73 | file.o \ | 74 | file.o \ |
| 74 | float_dsp.o \ | 75 | float_dsp.o \ |
| 76 | hmac.o \ | ||
| 75 | imgutils.o \ | 77 | imgutils.o \ |
| 76 | intfloat_readwrite.o \ | 78 | intfloat_readwrite.o \ |
| 77 | intmath.o \ | 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 | #define LIBAVUTIL_VERSION_MAJOR 52 | 77 | #define LIBAVUTIL_VERSION_MAJOR 52 |
| 78 | #define LIBAVUTIL_VERSION_MINOR 14 | 78 | #define LIBAVUTIL_VERSION_MINOR 15 |
| 79 | #define LIBAVUTIL_VERSION_MICRO 100 | 79 | #define LIBAVUTIL_VERSION_MICRO 100 |
| 80 | 80 | ||
| 81 | #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ | 81 | #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ |