1195972f6Sopenharmony_ci/**
2195972f6Sopenharmony_ci * @file
3195972f6Sopenharmony_ci * SNMPv3 crypto/auth functions implemented for ARM mbedtls.
4195972f6Sopenharmony_ci */
5195972f6Sopenharmony_ci
6195972f6Sopenharmony_ci/*
7195972f6Sopenharmony_ci * Copyright (c) 2016 Elias Oenal and Dirk Ziegelmeier.
8195972f6Sopenharmony_ci * All rights reserved.
9195972f6Sopenharmony_ci *
10195972f6Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
11195972f6Sopenharmony_ci * are permitted provided that the following conditions are met:
12195972f6Sopenharmony_ci *
13195972f6Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice,
14195972f6Sopenharmony_ci *    this list of conditions and the following disclaimer.
15195972f6Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice,
16195972f6Sopenharmony_ci *    this list of conditions and the following disclaimer in the documentation
17195972f6Sopenharmony_ci *    and/or other materials provided with the distribution.
18195972f6Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote products
19195972f6Sopenharmony_ci *    derived from this software without specific prior written permission.
20195972f6Sopenharmony_ci *
21195972f6Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
22195972f6Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23195972f6Sopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
24195972f6Sopenharmony_ci * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25195972f6Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
26195972f6Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27195972f6Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28195972f6Sopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29195972f6Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
30195972f6Sopenharmony_ci * OF SUCH DAMAGE.
31195972f6Sopenharmony_ci *
32195972f6Sopenharmony_ci * Author: Elias Oenal <lwip@eliasoenal.com>
33195972f6Sopenharmony_ci *         Dirk Ziegelmeier <dirk@ziegelmeier.net>
34195972f6Sopenharmony_ci */
35195972f6Sopenharmony_ci
36195972f6Sopenharmony_ci#include "lwip/apps/snmpv3.h"
37195972f6Sopenharmony_ci#include "snmpv3_priv.h"
38195972f6Sopenharmony_ci#include "lwip/arch.h"
39195972f6Sopenharmony_ci#include "snmp_msg.h"
40195972f6Sopenharmony_ci#include "lwip/sys.h"
41195972f6Sopenharmony_ci#include <string.h>
42195972f6Sopenharmony_ci
43195972f6Sopenharmony_ci#if LWIP_SNMP && LWIP_SNMP_V3 && LWIP_SNMP_V3_MBEDTLS
44195972f6Sopenharmony_ci
45195972f6Sopenharmony_ci#include "mbedtls/md.h"
46195972f6Sopenharmony_ci#include "mbedtls/cipher.h"
47195972f6Sopenharmony_ci
48195972f6Sopenharmony_ci#include "mbedtls/md5.h"
49195972f6Sopenharmony_ci#include "mbedtls/sha1.h"
50195972f6Sopenharmony_ci
51195972f6Sopenharmony_cierr_t
52195972f6Sopenharmony_cisnmpv3_auth(struct snmp_pbuf_stream *stream, u16_t length,
53195972f6Sopenharmony_ci            const u8_t *key, snmpv3_auth_algo_t algo, u8_t *hmac_out)
54195972f6Sopenharmony_ci{
55195972f6Sopenharmony_ci  u32_t i;
56195972f6Sopenharmony_ci  u8_t key_len;
57195972f6Sopenharmony_ci  const mbedtls_md_info_t *md_info;
58195972f6Sopenharmony_ci  mbedtls_md_context_t ctx;
59195972f6Sopenharmony_ci  struct snmp_pbuf_stream read_stream;
60195972f6Sopenharmony_ci  snmp_pbuf_stream_init(&read_stream, stream->pbuf, stream->offset, stream->length);
61195972f6Sopenharmony_ci
62195972f6Sopenharmony_ci  if (algo == SNMP_V3_AUTH_ALGO_MD5) {
63195972f6Sopenharmony_ci    md_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5);
64195972f6Sopenharmony_ci    key_len = SNMP_V3_MD5_LEN;
65195972f6Sopenharmony_ci  } else if (algo == SNMP_V3_AUTH_ALGO_SHA) {
66195972f6Sopenharmony_ci    md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
67195972f6Sopenharmony_ci    key_len = SNMP_V3_SHA_LEN;
68195972f6Sopenharmony_ci  } else {
69195972f6Sopenharmony_ci    return ERR_ARG;
70195972f6Sopenharmony_ci  }
71195972f6Sopenharmony_ci
72195972f6Sopenharmony_ci  mbedtls_md_init(&ctx);
73195972f6Sopenharmony_ci  if (mbedtls_md_setup(&ctx, md_info, 1) != 0) {
74195972f6Sopenharmony_ci    return ERR_ARG;
75195972f6Sopenharmony_ci  }
76195972f6Sopenharmony_ci
77195972f6Sopenharmony_ci  if (mbedtls_md_hmac_starts(&ctx, key, key_len) != 0) {
78195972f6Sopenharmony_ci    goto free_md;
79195972f6Sopenharmony_ci  }
80195972f6Sopenharmony_ci
81195972f6Sopenharmony_ci  for (i = 0; i < length; i++) {
82195972f6Sopenharmony_ci    u8_t byte;
83195972f6Sopenharmony_ci
84195972f6Sopenharmony_ci    if (snmp_pbuf_stream_read(&read_stream, &byte)) {
85195972f6Sopenharmony_ci      goto free_md;
86195972f6Sopenharmony_ci    }
87195972f6Sopenharmony_ci
88195972f6Sopenharmony_ci    if (mbedtls_md_hmac_update(&ctx, &byte, 1) != 0) {
89195972f6Sopenharmony_ci      goto free_md;
90195972f6Sopenharmony_ci    }
91195972f6Sopenharmony_ci  }
92195972f6Sopenharmony_ci
93195972f6Sopenharmony_ci  if (mbedtls_md_hmac_finish(&ctx, hmac_out) != 0) {
94195972f6Sopenharmony_ci    goto free_md;
95195972f6Sopenharmony_ci  }
96195972f6Sopenharmony_ci
97195972f6Sopenharmony_ci  mbedtls_md_free(&ctx);
98195972f6Sopenharmony_ci  return ERR_OK;
99195972f6Sopenharmony_ci
100195972f6Sopenharmony_cifree_md:
101195972f6Sopenharmony_ci  mbedtls_md_free(&ctx);
102195972f6Sopenharmony_ci  return ERR_ARG;
103195972f6Sopenharmony_ci}
104195972f6Sopenharmony_ci
105195972f6Sopenharmony_ci#if LWIP_SNMP_V3_CRYPTO
106195972f6Sopenharmony_ci
107195972f6Sopenharmony_cierr_t
108195972f6Sopenharmony_cisnmpv3_crypt(struct snmp_pbuf_stream *stream, u16_t length,
109195972f6Sopenharmony_ci             const u8_t *key, const u8_t *priv_param, const u32_t engine_boots,
110195972f6Sopenharmony_ci             const u32_t engine_time, snmpv3_priv_algo_t algo, snmpv3_priv_mode_t mode)
111195972f6Sopenharmony_ci{
112195972f6Sopenharmony_ci  size_t i;
113195972f6Sopenharmony_ci  mbedtls_cipher_context_t ctx;
114195972f6Sopenharmony_ci  const mbedtls_cipher_info_t *cipher_info;
115195972f6Sopenharmony_ci
116195972f6Sopenharmony_ci  struct snmp_pbuf_stream read_stream;
117195972f6Sopenharmony_ci  struct snmp_pbuf_stream write_stream;
118195972f6Sopenharmony_ci  snmp_pbuf_stream_init(&read_stream, stream->pbuf, stream->offset, stream->length);
119195972f6Sopenharmony_ci  snmp_pbuf_stream_init(&write_stream, stream->pbuf, stream->offset, stream->length);
120195972f6Sopenharmony_ci  mbedtls_cipher_init(&ctx);
121195972f6Sopenharmony_ci
122195972f6Sopenharmony_ci  if (algo == SNMP_V3_PRIV_ALGO_DES) {
123195972f6Sopenharmony_ci    u8_t iv_local[8];
124195972f6Sopenharmony_ci    u8_t out_bytes[8];
125195972f6Sopenharmony_ci    size_t out_len;
126195972f6Sopenharmony_ci
127195972f6Sopenharmony_ci    /* RFC 3414 mandates padding for DES */
128195972f6Sopenharmony_ci    if ((length & 0x07) != 0) {
129195972f6Sopenharmony_ci      return ERR_ARG;
130195972f6Sopenharmony_ci    }
131195972f6Sopenharmony_ci
132195972f6Sopenharmony_ci    cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_CBC);
133195972f6Sopenharmony_ci    if (mbedtls_cipher_setup(&ctx, cipher_info) != 0) {
134195972f6Sopenharmony_ci      return ERR_ARG;
135195972f6Sopenharmony_ci    }
136195972f6Sopenharmony_ci    if (mbedtls_cipher_set_padding_mode(&ctx, MBEDTLS_PADDING_NONE) != 0) {
137195972f6Sopenharmony_ci      return ERR_ARG;
138195972f6Sopenharmony_ci    }
139195972f6Sopenharmony_ci    if (mbedtls_cipher_setkey(&ctx, key, 8 * 8, (mode == SNMP_V3_PRIV_MODE_ENCRYPT) ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT) != 0) {
140195972f6Sopenharmony_ci      goto error;
141195972f6Sopenharmony_ci    }
142195972f6Sopenharmony_ci
143195972f6Sopenharmony_ci    /* Prepare IV */
144195972f6Sopenharmony_ci    for (i = 0; i < LWIP_ARRAYSIZE(iv_local); i++) {
145195972f6Sopenharmony_ci      iv_local[i] = priv_param[i] ^ key[i + 8];
146195972f6Sopenharmony_ci    }
147195972f6Sopenharmony_ci    if (mbedtls_cipher_set_iv(&ctx, iv_local, LWIP_ARRAYSIZE(iv_local)) != 0) {
148195972f6Sopenharmony_ci      goto error;
149195972f6Sopenharmony_ci    }
150195972f6Sopenharmony_ci
151195972f6Sopenharmony_ci    for (i = 0; i < length; i += 8) {
152195972f6Sopenharmony_ci      size_t j;
153195972f6Sopenharmony_ci      u8_t in_bytes[8];
154195972f6Sopenharmony_ci      out_len = LWIP_ARRAYSIZE(out_bytes) ;
155195972f6Sopenharmony_ci
156195972f6Sopenharmony_ci      for (j = 0; j < LWIP_ARRAYSIZE(in_bytes); j++) {
157195972f6Sopenharmony_ci        if (snmp_pbuf_stream_read(&read_stream, &in_bytes[j]) != ERR_OK) {
158195972f6Sopenharmony_ci          goto error;
159195972f6Sopenharmony_ci        }
160195972f6Sopenharmony_ci      }
161195972f6Sopenharmony_ci
162195972f6Sopenharmony_ci      if (mbedtls_cipher_update(&ctx, in_bytes, LWIP_ARRAYSIZE(in_bytes), out_bytes, &out_len) != 0) {
163195972f6Sopenharmony_ci        goto error;
164195972f6Sopenharmony_ci      }
165195972f6Sopenharmony_ci
166195972f6Sopenharmony_ci      if (snmp_pbuf_stream_writebuf(&write_stream, out_bytes, (u16_t)out_len) != ERR_OK) {
167195972f6Sopenharmony_ci        goto error;
168195972f6Sopenharmony_ci      }
169195972f6Sopenharmony_ci    }
170195972f6Sopenharmony_ci
171195972f6Sopenharmony_ci    out_len = LWIP_ARRAYSIZE(out_bytes);
172195972f6Sopenharmony_ci    if (mbedtls_cipher_finish(&ctx, out_bytes, &out_len) != 0) {
173195972f6Sopenharmony_ci      goto error;
174195972f6Sopenharmony_ci    }
175195972f6Sopenharmony_ci
176195972f6Sopenharmony_ci    if (snmp_pbuf_stream_writebuf(&write_stream, out_bytes, (u16_t)out_len) != ERR_OK) {
177195972f6Sopenharmony_ci      goto error;
178195972f6Sopenharmony_ci    }
179195972f6Sopenharmony_ci  } else if (algo == SNMP_V3_PRIV_ALGO_AES) {
180195972f6Sopenharmony_ci    u8_t iv_local[16];
181195972f6Sopenharmony_ci
182195972f6Sopenharmony_ci    cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_CFB128);
183195972f6Sopenharmony_ci    if (mbedtls_cipher_setup(&ctx, cipher_info) != 0) {
184195972f6Sopenharmony_ci      return ERR_ARG;
185195972f6Sopenharmony_ci    }
186195972f6Sopenharmony_ci    if (mbedtls_cipher_setkey(&ctx, key, 16 * 8, (mode == SNMP_V3_PRIV_MODE_ENCRYPT) ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT) != 0) {
187195972f6Sopenharmony_ci      goto error;
188195972f6Sopenharmony_ci    }
189195972f6Sopenharmony_ci
190195972f6Sopenharmony_ci    /*
191195972f6Sopenharmony_ci     * IV is the big endian concatenation of boots,
192195972f6Sopenharmony_ci     * uptime and priv param - see RFC3826.
193195972f6Sopenharmony_ci     */
194195972f6Sopenharmony_ci    iv_local[0 + 0] = (engine_boots >> 24) & 0xFF;
195195972f6Sopenharmony_ci    iv_local[0 + 1] = (engine_boots >> 16) & 0xFF;
196195972f6Sopenharmony_ci    iv_local[0 + 2] = (engine_boots >>  8) & 0xFF;
197195972f6Sopenharmony_ci    iv_local[0 + 3] = (engine_boots >>  0) & 0xFF;
198195972f6Sopenharmony_ci    iv_local[4 + 0] = (engine_time  >> 24) & 0xFF;
199195972f6Sopenharmony_ci    iv_local[4 + 1] = (engine_time  >> 16) & 0xFF;
200195972f6Sopenharmony_ci    iv_local[4 + 2] = (engine_time  >>  8) & 0xFF;
201195972f6Sopenharmony_ci    iv_local[4 + 3] = (engine_time  >>  0) & 0xFF;
202195972f6Sopenharmony_ci    SMEMCPY(iv_local + 8, priv_param, 8);
203195972f6Sopenharmony_ci    if (mbedtls_cipher_set_iv(&ctx, iv_local, LWIP_ARRAYSIZE(iv_local)) != 0) {
204195972f6Sopenharmony_ci      goto error;
205195972f6Sopenharmony_ci    }
206195972f6Sopenharmony_ci
207195972f6Sopenharmony_ci    for (i = 0; i < length; i++) {
208195972f6Sopenharmony_ci      u8_t in_byte;
209195972f6Sopenharmony_ci      u8_t out_byte;
210195972f6Sopenharmony_ci      size_t out_len = sizeof(out_byte);
211195972f6Sopenharmony_ci
212195972f6Sopenharmony_ci      if (snmp_pbuf_stream_read(&read_stream, &in_byte) != ERR_OK) {
213195972f6Sopenharmony_ci        goto error;
214195972f6Sopenharmony_ci      }
215195972f6Sopenharmony_ci      if (mbedtls_cipher_update(&ctx, &in_byte, sizeof(in_byte), &out_byte, &out_len) != 0) {
216195972f6Sopenharmony_ci        goto error;
217195972f6Sopenharmony_ci      }
218195972f6Sopenharmony_ci      if (snmp_pbuf_stream_write(&write_stream, out_byte) != ERR_OK) {
219195972f6Sopenharmony_ci        goto error;
220195972f6Sopenharmony_ci      }
221195972f6Sopenharmony_ci    }
222195972f6Sopenharmony_ci  } else {
223195972f6Sopenharmony_ci    return ERR_ARG;
224195972f6Sopenharmony_ci  }
225195972f6Sopenharmony_ci
226195972f6Sopenharmony_ci  mbedtls_cipher_free(&ctx);
227195972f6Sopenharmony_ci  return ERR_OK;
228195972f6Sopenharmony_ci
229195972f6Sopenharmony_cierror:
230195972f6Sopenharmony_ci  mbedtls_cipher_free(&ctx);
231195972f6Sopenharmony_ci  return ERR_OK;
232195972f6Sopenharmony_ci}
233195972f6Sopenharmony_ci
234195972f6Sopenharmony_ci#endif /* LWIP_SNMP_V3_CRYPTO */
235195972f6Sopenharmony_ci
236195972f6Sopenharmony_ci/* A.2.1. Password to Key Sample Code for MD5 */
237195972f6Sopenharmony_civoid
238195972f6Sopenharmony_cisnmpv3_password_to_key_md5(
239195972f6Sopenharmony_ci  const u8_t *password,    /* IN */
240195972f6Sopenharmony_ci  size_t      passwordlen, /* IN */
241195972f6Sopenharmony_ci  const u8_t *engineID,    /* IN  - pointer to snmpEngineID  */
242195972f6Sopenharmony_ci  u8_t        engineLength,/* IN  - length of snmpEngineID */
243195972f6Sopenharmony_ci  u8_t       *key)         /* OUT - pointer to caller 16-octet buffer */
244195972f6Sopenharmony_ci{
245195972f6Sopenharmony_ci  mbedtls_md5_context MD;
246195972f6Sopenharmony_ci  u8_t *cp, password_buf[64];
247195972f6Sopenharmony_ci  u32_t password_index = 0;
248195972f6Sopenharmony_ci  u8_t i;
249195972f6Sopenharmony_ci  u32_t count = 0;
250195972f6Sopenharmony_ci
251195972f6Sopenharmony_ci  mbedtls_md5_init(&MD); /* initialize MD5 */
252195972f6Sopenharmony_ci  mbedtls_md5_starts(&MD);
253195972f6Sopenharmony_ci
254195972f6Sopenharmony_ci  /**********************************************/
255195972f6Sopenharmony_ci  /* Use while loop until we've done 1 Megabyte */
256195972f6Sopenharmony_ci  /**********************************************/
257195972f6Sopenharmony_ci  while (count < 1048576) {
258195972f6Sopenharmony_ci    cp = password_buf;
259195972f6Sopenharmony_ci    for (i = 0; i < 64; i++) {
260195972f6Sopenharmony_ci      /*************************************************/
261195972f6Sopenharmony_ci      /* Take the next octet of the password, wrapping */
262195972f6Sopenharmony_ci      /* to the beginning of the password as necessary.*/
263195972f6Sopenharmony_ci      /*************************************************/
264195972f6Sopenharmony_ci      *cp++ = password[password_index++ % passwordlen];
265195972f6Sopenharmony_ci    }
266195972f6Sopenharmony_ci    mbedtls_md5_update(&MD, password_buf, 64);
267195972f6Sopenharmony_ci    count += 64;
268195972f6Sopenharmony_ci  }
269195972f6Sopenharmony_ci  mbedtls_md5_finish(&MD, key); /* tell MD5 we're done */
270195972f6Sopenharmony_ci
271195972f6Sopenharmony_ci  /*****************************************************/
272195972f6Sopenharmony_ci  /* Now localize the key with the engineID and pass   */
273195972f6Sopenharmony_ci  /* through MD5 to produce final key                  */
274195972f6Sopenharmony_ci  /* May want to ensure that engineLength <= 32,       */
275195972f6Sopenharmony_ci  /* otherwise need to use a buffer larger than 64     */
276195972f6Sopenharmony_ci  /*****************************************************/
277195972f6Sopenharmony_ci  SMEMCPY(password_buf, key, 16);
278195972f6Sopenharmony_ci  MEMCPY(password_buf + 16, engineID, engineLength);
279195972f6Sopenharmony_ci  SMEMCPY(password_buf + 16 + engineLength, key, 16);
280195972f6Sopenharmony_ci
281195972f6Sopenharmony_ci  mbedtls_md5_starts(&MD);
282195972f6Sopenharmony_ci  mbedtls_md5_update(&MD, password_buf, 32 + engineLength);
283195972f6Sopenharmony_ci  mbedtls_md5_finish(&MD, key);
284195972f6Sopenharmony_ci
285195972f6Sopenharmony_ci  mbedtls_md5_free(&MD);
286195972f6Sopenharmony_ci  return;
287195972f6Sopenharmony_ci}
288195972f6Sopenharmony_ci
289195972f6Sopenharmony_ci/* A.2.2. Password to Key Sample Code for SHA */
290195972f6Sopenharmony_civoid
291195972f6Sopenharmony_cisnmpv3_password_to_key_sha(
292195972f6Sopenharmony_ci  const u8_t *password,    /* IN */
293195972f6Sopenharmony_ci  size_t      passwordlen, /* IN */
294195972f6Sopenharmony_ci  const u8_t *engineID,    /* IN  - pointer to snmpEngineID  */
295195972f6Sopenharmony_ci  u8_t        engineLength,/* IN  - length of snmpEngineID */
296195972f6Sopenharmony_ci  u8_t       *key)         /* OUT - pointer to caller 20-octet buffer */
297195972f6Sopenharmony_ci{
298195972f6Sopenharmony_ci  mbedtls_sha1_context SH;
299195972f6Sopenharmony_ci  u8_t *cp, password_buf[72];
300195972f6Sopenharmony_ci  u32_t password_index = 0;
301195972f6Sopenharmony_ci  u8_t i;
302195972f6Sopenharmony_ci  u32_t count = 0;
303195972f6Sopenharmony_ci
304195972f6Sopenharmony_ci  mbedtls_sha1_init(&SH); /* initialize SHA */
305195972f6Sopenharmony_ci  mbedtls_sha1_starts(&SH);
306195972f6Sopenharmony_ci
307195972f6Sopenharmony_ci  /**********************************************/
308195972f6Sopenharmony_ci  /* Use while loop until we've done 1 Megabyte */
309195972f6Sopenharmony_ci  /**********************************************/
310195972f6Sopenharmony_ci  while (count < 1048576) {
311195972f6Sopenharmony_ci    cp = password_buf;
312195972f6Sopenharmony_ci    for (i = 0; i < 64; i++) {
313195972f6Sopenharmony_ci      /*************************************************/
314195972f6Sopenharmony_ci      /* Take the next octet of the password, wrapping */
315195972f6Sopenharmony_ci      /* to the beginning of the password as necessary.*/
316195972f6Sopenharmony_ci      /*************************************************/
317195972f6Sopenharmony_ci      *cp++ = password[password_index++ % passwordlen];
318195972f6Sopenharmony_ci    }
319195972f6Sopenharmony_ci    mbedtls_sha1_update(&SH, password_buf, 64);
320195972f6Sopenharmony_ci    count += 64;
321195972f6Sopenharmony_ci  }
322195972f6Sopenharmony_ci  mbedtls_sha1_finish(&SH, key); /* tell SHA we're done */
323195972f6Sopenharmony_ci
324195972f6Sopenharmony_ci  /*****************************************************/
325195972f6Sopenharmony_ci  /* Now localize the key with the engineID and pass   */
326195972f6Sopenharmony_ci  /* through SHA to produce final key                  */
327195972f6Sopenharmony_ci  /* May want to ensure that engineLength <= 32,       */
328195972f6Sopenharmony_ci  /* otherwise need to use a buffer larger than 72     */
329195972f6Sopenharmony_ci  /*****************************************************/
330195972f6Sopenharmony_ci  SMEMCPY(password_buf, key, 20);
331195972f6Sopenharmony_ci  MEMCPY(password_buf + 20, engineID, engineLength);
332195972f6Sopenharmony_ci  SMEMCPY(password_buf + 20 + engineLength, key, 20);
333195972f6Sopenharmony_ci
334195972f6Sopenharmony_ci  mbedtls_sha1_starts(&SH);
335195972f6Sopenharmony_ci  mbedtls_sha1_update(&SH, password_buf, 40 + engineLength);
336195972f6Sopenharmony_ci  mbedtls_sha1_finish(&SH, key);
337195972f6Sopenharmony_ci
338195972f6Sopenharmony_ci  mbedtls_sha1_free(&SH);
339195972f6Sopenharmony_ci  return;
340195972f6Sopenharmony_ci}
341195972f6Sopenharmony_ci
342195972f6Sopenharmony_ci#endif /* LWIP_SNMP && LWIP_SNMP_V3 && LWIP_SNMP_V3_MBEDTLS */
343