1 /*
2  *  Copyright 2014 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "pc/external_hmac.h"
12 
13 #include <stdlib.h>  // For malloc/free.
14 #include <string.h>
15 
16 #include "rtc_base/logging.h"
17 #include "rtc_base/zero_memory.h"
18 #include "third_party/libsrtp/include/srtp.h"
19 
20 // Begin test case 0 */
21 static const uint8_t kExternalHmacTestCase0Key[20] = {
22     0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
23     0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b};
24 
25 static const uint8_t kExternalHmacTestCase0Data[8] = {
26     0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65  // "Hi There"
27 };
28 
29 static const uint8_t kExternalHmacFakeTag[10] = {0xba, 0xdd, 0xba, 0xdd, 0xba,
30                                                  0xdd, 0xba, 0xdd, 0xba, 0xdd};
31 
32 static const srtp_auth_test_case_t kExternalHmacTestCase0 = {
33     20,                                                // Octets in key
34     const_cast<uint8_t*>(kExternalHmacTestCase0Key),   // Key
35     8,                                                 // Octets in data
36     const_cast<uint8_t*>(kExternalHmacTestCase0Data),  // Data
37     10,                                                // Octets in tag
38     const_cast<uint8_t*>(kExternalHmacFakeTag),        // Tag
39     NULL                                               // Pointer to next
40                                                        // testcase
41 };
42 
43 static const char kExternalHmacDescription[] =
44     "external hmac sha-1 authentication";
45 
46 // srtp_auth_type_t external_hmac is the hmac metaobject
47 
48 static const srtp_auth_type_t external_hmac = {
49     external_hmac_alloc,
50     external_hmac_dealloc,
51     external_hmac_init,
52     external_hmac_compute,
53     external_hmac_update,
54     external_hmac_start,
55     const_cast<char*>(kExternalHmacDescription),
56     const_cast<srtp_auth_test_case_t*>(&kExternalHmacTestCase0),
57     EXTERNAL_HMAC_SHA1};
58 
external_hmac_alloc(srtp_auth_t ** a,int key_len,int out_len)59 srtp_err_status_t external_hmac_alloc(srtp_auth_t** a,
60                                       int key_len,
61                                       int out_len) {
62   uint8_t* pointer;
63 
64   // Check key length - note that we don't support keys larger
65   // than 20 bytes yet
66   if (key_len > 20)
67     return srtp_err_status_bad_param;
68 
69   // Check output length - should be less than 20 bytes/
70   if (out_len > 20)
71     return srtp_err_status_bad_param;
72 
73   // Allocate memory for auth and hmac_ctx_t structures.
74   pointer = new uint8_t[(sizeof(ExternalHmacContext) + sizeof(srtp_auth_t))];
75   if (pointer == NULL)
76     return srtp_err_status_alloc_fail;
77 
78   // Set pointers
79   *a = reinterpret_cast<srtp_auth_t*>(pointer);
80   // |external_hmac| is const and libsrtp expects |type| to be non-const.
81   // const conversion is required. |external_hmac| is constant because we don't
82   // want to increase global count in Chrome.
83   (*a)->type = const_cast<srtp_auth_type_t*>(&external_hmac);
84   (*a)->state = pointer + sizeof(srtp_auth_t);
85   (*a)->out_len = out_len;
86   (*a)->key_len = key_len;
87   (*a)->prefix_len = 0;
88 
89   return srtp_err_status_ok;
90 }
91 
external_hmac_dealloc(srtp_auth_t * a)92 srtp_err_status_t external_hmac_dealloc(srtp_auth_t* a) {
93   rtc::ExplicitZeroMemory(a, sizeof(ExternalHmacContext) + sizeof(srtp_auth_t));
94 
95   // Free memory
96   delete[] a;
97 
98   return srtp_err_status_ok;
99 }
100 
external_hmac_init(void * state,const uint8_t * key,int key_len)101 srtp_err_status_t external_hmac_init(void* state,
102                                      const uint8_t* key,
103                                      int key_len) {
104   if (key_len > HMAC_KEY_LENGTH)
105     return srtp_err_status_bad_param;
106 
107   ExternalHmacContext* context = static_cast<ExternalHmacContext*>(state);
108   memcpy(context->key, key, key_len);
109   context->key_length = key_len;
110   return srtp_err_status_ok;
111 }
112 
external_hmac_start(void *)113 srtp_err_status_t external_hmac_start(void* /*state*/) {
114   return srtp_err_status_ok;
115 }
116 
external_hmac_update(void *,const uint8_t *,int)117 srtp_err_status_t external_hmac_update(void* /*state*/,
118                                        const uint8_t* /*message*/,
119                                        int /*msg_octets*/) {
120   return srtp_err_status_ok;
121 }
122 
external_hmac_compute(void *,const uint8_t *,int,int tag_len,uint8_t * result)123 srtp_err_status_t external_hmac_compute(void* /*state*/,
124                                         const uint8_t* /*message*/,
125                                         int /*msg_octets*/,
126                                         int tag_len,
127                                         uint8_t* result) {
128   memcpy(result, kExternalHmacFakeTag, tag_len);
129   return srtp_err_status_ok;
130 }
131 
external_crypto_init()132 srtp_err_status_t external_crypto_init() {
133   // |external_hmac| is const. const_cast is required as libsrtp expects
134   // non-const.
135   srtp_err_status_t status = srtp_replace_auth_type(
136       const_cast<srtp_auth_type_t*>(&external_hmac), EXTERNAL_HMAC_SHA1);
137   if (status) {
138     RTC_LOG(LS_ERROR) << "Error in replacing default auth module, error: "
139                       << status;
140     return srtp_err_status_fail;
141   }
142   return srtp_err_status_ok;
143 }
144