Coverage Report

Created: 2023-09-25 06:11

/src/dropbear/src/chachapoly.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Dropbear SSH
3
 * 
4
 * Copyright (c) 2002,2003 Matt Johnston
5
 * Copyright (c) 2020 by Vladislav Grishenko
6
 * All rights reserved.
7
 * 
8
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9
 * of this software and associated documentation files (the "Software"), to deal
10
 * in the Software without restriction, including without limitation the rights
11
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
 * copies of the Software, and to permit persons to whom the Software is
13
 * furnished to do so, subject to the following conditions:
14
 * 
15
 * The above copyright notice and this permission notice shall be included in
16
 * all copies or substantial portions of the Software.
17
 * 
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
 * SOFTWARE. */
25
26
#include "includes.h"
27
#include "algo.h"
28
#include "dbutil.h"
29
#include "chachapoly.h"
30
31
#if DROPBEAR_CHACHA20POLY1305
32
33
69.3k
#define CHACHA20_KEY_LEN 32
34
#define CHACHA20_BLOCKSIZE 8
35
#define POLY1305_KEY_LEN 32
36
239k
#define POLY1305_TAG_LEN 16
37
38
static const struct ltc_cipher_descriptor dummy = {.name = NULL};
39
40
static const struct dropbear_hash dropbear_chachapoly_mac =
41
  {NULL, POLY1305_KEY_LEN, POLY1305_TAG_LEN};
42
43
const struct dropbear_cipher dropbear_chachapoly =
44
  {&dummy, CHACHA20_KEY_LEN*2, CHACHA20_BLOCKSIZE};
45
46
static int dropbear_chachapoly_start(int UNUSED(cipher), const unsigned char* UNUSED(IV),
47
      const unsigned char *key, int keylen,
48
17.3k
      int UNUSED(num_rounds), dropbear_chachapoly_state *state) {
49
17.3k
  int err;
50
51
17.3k
  TRACE2(("enter dropbear_chachapoly_start"))
52
53
17.3k
  if (keylen != CHACHA20_KEY_LEN*2) {
54
0
    return CRYPT_ERROR;
55
0
  }
56
57
17.3k
  if ((err = chacha_setup(&state->chacha, key,
58
17.3k
        CHACHA20_KEY_LEN, 20)) != CRYPT_OK) {
59
0
    return err;
60
0
  }
61
62
17.3k
  if ((err = chacha_setup(&state->header, key + CHACHA20_KEY_LEN,
63
17.3k
        CHACHA20_KEY_LEN, 20) != CRYPT_OK)) {
64
0
    return err;
65
0
  }
66
67
17.3k
  TRACE2(("leave dropbear_chachapoly_start"))
68
17.3k
  return CRYPT_OK;
69
17.3k
}
70
71
static int dropbear_chachapoly_crypt(unsigned int seq,
72
      const unsigned char *in, unsigned char *out,
73
      unsigned long len, unsigned long taglen,
74
239k
      dropbear_chachapoly_state *state, int direction) {
75
239k
  poly1305_state poly;
76
239k
  unsigned char seqbuf[8], key[POLY1305_KEY_LEN], tag[POLY1305_TAG_LEN];
77
239k
  int err;
78
79
239k
  TRACE2(("enter dropbear_chachapoly_crypt"))
80
81
239k
  if (len < 4 || taglen != POLY1305_TAG_LEN) {
82
0
    return CRYPT_ERROR;
83
0
  }
84
85
239k
  STORE64H((uint64_t)seq, seqbuf);
86
239k
  chacha_ivctr64(&state->chacha, seqbuf, sizeof(seqbuf), 0);
87
239k
  if ((err = chacha_keystream(&state->chacha, key, sizeof(key))) != CRYPT_OK) {
88
0
    return err;
89
0
  }
90
91
239k
  poly1305_init(&poly, key, sizeof(key));
92
239k
  if (direction == LTC_DECRYPT) {
93
0
    poly1305_process(&poly, in, len);
94
0
    poly1305_done(&poly, tag, &taglen);
95
0
    if (constant_time_memcmp(in + len, tag, taglen) != 0) {
96
0
      return CRYPT_ERROR;
97
0
    }
98
0
  }
99
100
239k
  chacha_ivctr64(&state->header, seqbuf, sizeof(seqbuf), 0);
101
239k
  if ((err = chacha_crypt(&state->header, in, 4, out)) != CRYPT_OK) {
102
0
    return err;
103
0
  }
104
105
239k
  chacha_ivctr64(&state->chacha, seqbuf, sizeof(seqbuf), 1);
106
239k
  if ((err = chacha_crypt(&state->chacha, in + 4, len - 4, out + 4)) != CRYPT_OK) {
107
0
    return err;
108
0
  }
109
110
239k
  if (direction == LTC_ENCRYPT) {
111
239k
    poly1305_process(&poly, out, len);
112
239k
    poly1305_done(&poly, out + len, &taglen);
113
239k
  }
114
115
239k
  TRACE2(("leave dropbear_chachapoly_crypt"))
116
239k
  return CRYPT_OK;
117
239k
}
118
119
static int dropbear_chachapoly_getlength(unsigned int seq,
120
      const unsigned char *in, unsigned int *outlen,
121
0
      unsigned long len, dropbear_chachapoly_state *state) {
122
0
  unsigned char seqbuf[8], buf[4];
123
0
  int err;
124
125
0
  TRACE2(("enter dropbear_chachapoly_getlength"))
126
127
0
  if (len < sizeof(buf)) {
128
0
    return CRYPT_ERROR;
129
0
  }
130
131
0
  STORE64H((uint64_t)seq, seqbuf);
132
0
  chacha_ivctr64(&state->header, seqbuf, sizeof(seqbuf), 0);
133
0
  if ((err = chacha_crypt(&state->header, in, sizeof(buf), buf)) != CRYPT_OK) {
134
0
    return err;
135
0
  }
136
137
0
  LOAD32H(*outlen, buf);
138
139
0
  TRACE2(("leave dropbear_chachapoly_getlength"))
140
0
  return CRYPT_OK;
141
0
}
142
143
const struct dropbear_cipher_mode dropbear_mode_chachapoly =
144
  {(void *)dropbear_chachapoly_start, NULL, NULL,
145
   (void *)dropbear_chachapoly_crypt,
146
   (void *)dropbear_chachapoly_getlength, &dropbear_chachapoly_mac};
147
148
#endif /* DROPBEAR_CHACHA20POLY1305 */