Coverage Report

Created: 2023-03-26 07:40

/src/libssh/src/dh.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * dh.c - Diffie-Helman algorithm code against SSH 2
3
 *
4
 * This file is part of the SSH Library
5
 *
6
 * Copyright (c) 2003-2018 by Aris Adamantiadis
7
 * Copyright (c) 2009-2013 by Andreas Schneider <asn@cryptomilk.org>
8
 * Copyright (c) 2012      by Dmitriy Kuznetsov <dk@yandex.ru>
9
 *
10
 * The SSH Library is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU Lesser General Public License as published by
12
 * the Free Software Foundation; either version 2.1 of the License, or (at your
13
 * option) any later version.
14
 *
15
 * The SSH Library is distributed in the hope that it will be useful, but
16
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
18
 * License for more details.
19
 *
20
 * You should have received a copy of the GNU Lesser General Public License
21
 * along with the SSH Library; see the file COPYING.  If not, write to
22
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23
 * MA 02111-1307, USA.
24
 */
25
26
#include "config.h"
27
28
#include <stdio.h>
29
30
#include "libssh/priv.h"
31
#include "libssh/crypto.h"
32
#include "libssh/buffer.h"
33
#include "libssh/session.h"
34
#include "libssh/misc.h"
35
#include "libssh/dh.h"
36
#include "libssh/ssh2.h"
37
#include "libssh/pki.h"
38
#include "libssh/bignum.h"
39
40
static unsigned char p_group1_value[] = {
41
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
42
        0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
43
        0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
44
        0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
45
        0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
46
        0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
47
        0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
48
        0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
49
        0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
50
        0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
51
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
52
#define P_GROUP1_LEN 128  /* Size in bytes of the p number */
53
54
static unsigned char p_group14_value[] = {
55
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
56
        0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
57
        0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
58
        0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
59
        0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
60
        0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
61
        0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
62
        0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
63
        0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
64
        0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
65
        0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
66
        0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
67
        0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
68
        0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
69
        0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
70
        0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
71
        0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
72
        0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
73
        0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
74
        0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
75
        0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF,
76
        0xFF, 0xFF, 0xFF, 0xFF};
77
78
#define P_GROUP14_LEN 256 /* Size in bytes of the p number for group 14 */
79
80
static unsigned char p_group16_value[] = {
81
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
82
    0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
83
    0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
84
    0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
85
    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
86
    0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
87
    0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
88
    0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
89
    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
90
    0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
91
    0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
92
    0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
93
    0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
94
    0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
95
    0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
96
    0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
97
    0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
98
    0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
99
    0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
100
    0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
101
    0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
102
    0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
103
    0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
104
    0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
105
    0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
106
    0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
107
    0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
108
    0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
109
    0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
110
    0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
111
    0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
112
    0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
113
    0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
114
    0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
115
    0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
116
    0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
117
    0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
118
    0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
119
    0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
120
    0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
121
    0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
122
    0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
123
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
124
125
#define P_GROUP16_LEN 512 /* Size in bytes of the p number for group 16 */
126
127
static unsigned char p_group18_value[] = {
128
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
129
    0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
130
    0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
131
    0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
132
    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
133
    0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
134
    0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
135
    0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
136
    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
137
    0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
138
    0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
139
    0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
140
    0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
141
    0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
142
    0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
143
    0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
144
    0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
145
    0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
146
    0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
147
    0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
148
    0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
149
    0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
150
    0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
151
    0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
152
    0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
153
    0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
154
    0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
155
    0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
156
    0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
157
    0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
158
    0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
159
    0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
160
    0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
161
    0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
162
    0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
163
    0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
164
    0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
165
    0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
166
    0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
167
    0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
168
    0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
169
    0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92,
170
    0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, 0xC1, 0xD4, 0xDC, 0xB2,
171
    0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
172
    0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F,
173
    0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31,
174
    0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, 0xDA, 0x3E, 0xDB, 0xEB,
175
    0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
176
    0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51,
177
    0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF,
178
    0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, 0x32, 0xEA, 0x15,
179
    0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
180
    0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31,
181
    0x90, 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3,
182
    0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, 0x45, 0xB7,
183
    0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
184
    0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2,
185
    0x0F, 0x80, 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28,
186
    0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, 0x3D,
187
    0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
188
    0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7,
189
    0x6E, 0x3C, 0x04, 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE,
190
    0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E,
191
    0x6D, 0xBE, 0x11, 0x59, 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4,
192
    0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, 0xD8, 0xBE, 0xC4, 0xD0,
193
    0x73, 0xB9, 0x31, 0xBA, 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00,
194
    0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, 0x25, 0x76, 0xF6, 0x93,
195
    0x6B, 0xA4, 0x24, 0x66, 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68,
196
    0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, 0x23, 0x8F, 0x16, 0xCB,
197
    0xE3, 0x9D, 0x65, 0x2D, 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9,
198
    0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, 0x13, 0xEB, 0x57, 0xA8,
199
    0x1A, 0x23, 0xF0, 0xC7, 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B,
200
    0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, 0xFA, 0x9D, 0x4B, 0x7F,
201
    0xA2, 0xC0, 0x87, 0xE8, 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A,
202
    0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, 0x6D, 0x2A, 0x13, 0xF8,
203
    0x3F, 0x44, 0xF8, 0x2D, 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36,
204
    0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, 0x64, 0xF3, 0x1C, 0xC5,
205
    0x08, 0x46, 0x85, 0x1D, 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1,
206
    0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, 0xFA, 0xF3, 0x6B, 0xC3,
207
    0x1E, 0xCF, 0xA2, 0x68, 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92,
208
    0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, 0x88, 0x9A, 0x00, 0x2E,
209
    0xD5, 0xEE, 0x38, 0x2B, 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47,
210
    0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, 0x9E, 0x30, 0x50, 0xE2,
211
    0x76, 0x56, 0x94, 0xDF, 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71,
212
    0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF,
213
    0xFF, 0xFF, 0xFF, 0xFF};
214
215
#define P_GROUP18_LEN 1024 /* Size in bytes of the p number for group 18 */
216
217
bignum ssh_dh_generator;
218
bignum ssh_dh_group1;
219
bignum ssh_dh_group14;
220
bignum ssh_dh_group16;
221
bignum ssh_dh_group18;
222
static int dh_crypto_initialized;
223
224
/**
225
 * @internal
226
 * @brief Initialize global constants used in DH key agreement
227
 * @return SSH_OK on success, SSH_ERROR otherwise.
228
 */
229
int ssh_dh_init(void)
230
2
{
231
2
    unsigned long g_int = 2 ; /* G is defined as 2 by the ssh2 standards */
232
2
    int rc;
233
2
    if (dh_crypto_initialized) {
234
0
        return SSH_OK;
235
0
    }
236
2
    dh_crypto_initialized = 1;
237
238
2
    ssh_dh_generator = bignum_new();
239
2
    if (ssh_dh_generator == NULL) {
240
0
        goto error;
241
0
    }
242
2
    rc = bignum_set_word(ssh_dh_generator, g_int);
243
2
    if (rc != 1) {
244
0
        goto error;
245
0
    }
246
247
2
    bignum_bin2bn(p_group1_value, P_GROUP1_LEN, &ssh_dh_group1);
248
2
    if (ssh_dh_group1 == NULL) {
249
0
        goto error;
250
0
    }
251
2
    bignum_bin2bn(p_group14_value, P_GROUP14_LEN, &ssh_dh_group14);
252
2
    if (ssh_dh_group14 == NULL) {
253
0
        goto error;
254
0
    }
255
2
    bignum_bin2bn(p_group16_value, P_GROUP16_LEN, &ssh_dh_group16);
256
2
    if (ssh_dh_group16 == NULL) {
257
0
        goto error;
258
0
    }
259
2
    bignum_bin2bn(p_group18_value, P_GROUP18_LEN, &ssh_dh_group18);
260
2
    if (ssh_dh_group18 == NULL) {
261
0
        goto error;
262
0
    }
263
264
2
    return 0;
265
0
error:
266
0
    ssh_dh_finalize();
267
0
    return SSH_ERROR;
268
2
}
269
270
/**
271
 * @internal
272
 * @brief Finalize and free global constants used in DH key agreement
273
 */
274
void ssh_dh_finalize(void)
275
0
{
276
0
    if (!dh_crypto_initialized) {
277
0
        return;
278
0
    }
279
280
0
    bignum_safe_free(ssh_dh_generator);
281
0
    bignum_safe_free(ssh_dh_group1);
282
0
    bignum_safe_free(ssh_dh_group14);
283
0
    bignum_safe_free(ssh_dh_group16);
284
0
    bignum_safe_free(ssh_dh_group18);
285
286
0
    dh_crypto_initialized = 0;
287
0
}
288
289
int ssh_dh_import_next_pubkey_blob(ssh_session session, ssh_string pubkey_blob)
290
0
{
291
0
    return ssh_pki_import_pubkey_blob(pubkey_blob,
292
0
                                      &session->next_crypto->server_pubkey);
293
294
0
}
295
296
static SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply);
297
298
static ssh_packet_callback dh_client_callbacks[]= {
299
    ssh_packet_client_dh_reply
300
};
301
302
static struct ssh_packet_callbacks_struct ssh_dh_client_callbacks = {
303
    .start = SSH2_MSG_KEXDH_REPLY,
304
    .n_callbacks = 1,
305
    .callbacks = dh_client_callbacks,
306
    .user = NULL
307
};
308
309
/** @internal
310
 * @brief Starts diffie-hellman-group1 key exchange
311
 */
312
0
int ssh_client_dh_init(ssh_session session){
313
0
  struct ssh_crypto_struct *crypto = session->next_crypto;
314
0
#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L
315
0
  const_bignum pubkey;
316
#else
317
  bignum pubkey = NULL;
318
#endif /* OPENSSL_VERSION_NUMBER */
319
0
  int rc;
320
321
0
  rc = ssh_dh_init_common(crypto);
322
0
  if (rc == SSH_ERROR) {
323
0
    goto error;
324
0
  }
325
326
0
  rc = ssh_dh_keypair_gen_keys(crypto->dh_ctx, DH_CLIENT_KEYPAIR);
327
0
  if (rc == SSH_ERROR){
328
0
      goto error;
329
0
  }
330
0
  rc = ssh_dh_keypair_get_keys(crypto->dh_ctx, DH_CLIENT_KEYPAIR,
331
0
                               NULL, &pubkey);
332
0
  if (rc != SSH_OK) {
333
0
    goto error;
334
0
  }
335
0
  rc = ssh_buffer_pack(session->out_buffer, "bB", SSH2_MSG_KEXDH_INIT, pubkey);
336
0
  if (rc != SSH_OK) {
337
0
    goto error;
338
0
  }
339
#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L
340
  bignum_safe_free(pubkey);
341
#endif
342
343
  /* register the packet callbacks */
344
0
  ssh_packet_set_callbacks(session, &ssh_dh_client_callbacks);
345
0
  session->dh_handshake_state = DH_STATE_INIT_SENT;
346
347
0
  rc = ssh_packet_send(session);
348
0
  return rc;
349
0
error:
350
#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L
351
  bignum_safe_free(pubkey);
352
#endif
353
0
  ssh_dh_cleanup(crypto);
354
0
  return SSH_ERROR;
355
0
}
356
357
0
SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){
358
0
  struct ssh_crypto_struct *crypto=session->next_crypto;
359
0
  ssh_string pubkey_blob = NULL;
360
0
  bignum server_pubkey;
361
0
  int rc;
362
363
0
  (void)type;
364
0
  (void)user;
365
366
0
  ssh_packet_remove_callbacks(session, &ssh_dh_client_callbacks);
367
368
0
  rc = ssh_buffer_unpack(packet, "SBS", &pubkey_blob, &server_pubkey,
369
0
          &crypto->dh_server_signature);
370
0
  if (rc == SSH_ERROR) {
371
0
      goto error;
372
0
  }
373
0
  rc = ssh_dh_keypair_set_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR,
374
0
                               NULL, server_pubkey);
375
0
  if (rc != SSH_OK) {
376
0
      SSH_STRING_FREE(pubkey_blob);
377
0
      bignum_safe_free(server_pubkey);
378
0
      goto error;
379
0
  }
380
0
  rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob);
381
0
  SSH_STRING_FREE(pubkey_blob);
382
0
  if (rc != 0) {
383
0
      goto error;
384
0
  }
385
386
0
  rc = ssh_dh_compute_shared_secret(session->next_crypto->dh_ctx,
387
0
                                    DH_CLIENT_KEYPAIR, DH_SERVER_KEYPAIR,
388
0
                                    &session->next_crypto->shared_secret);
389
0
  ssh_dh_debug_crypto(session->next_crypto);
390
0
  if (rc == SSH_ERROR){
391
0
    ssh_set_error(session, SSH_FATAL, "Could not generate shared secret");
392
0
    goto error;
393
0
  }
394
395
  /* Send the MSG_NEWKEYS */
396
0
  if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
397
0
    goto error;
398
0
  }
399
400
0
  rc=ssh_packet_send(session);
401
0
  if (rc == SSH_ERROR) {
402
0
    goto error;
403
0
  }
404
405
0
  SSH_LOG(SSH_LOG_DEBUG, "SSH_MSG_NEWKEYS sent");
406
0
  session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
407
0
  return SSH_PACKET_USED;
408
0
error:
409
0
  ssh_dh_cleanup(session->next_crypto);
410
0
  session->session_state=SSH_SESSION_STATE_ERROR;
411
0
  return SSH_PACKET_USED;
412
0
}
413
414
#ifdef WITH_SERVER
415
416
static SSH_PACKET_CALLBACK(ssh_packet_server_dh_init);
417
418
static ssh_packet_callback dh_server_callbacks[] = {
419
    ssh_packet_server_dh_init,
420
};
421
422
static struct ssh_packet_callbacks_struct ssh_dh_server_callbacks = {
423
    .start = SSH2_MSG_KEXDH_INIT,
424
    .n_callbacks = 1,
425
    .callbacks = dh_server_callbacks,
426
    .user = NULL
427
};
428
429
/** @internal
430
 * @brief sets up the diffie-hellman-groupx kex callbacks
431
 */
432
0
void ssh_server_dh_init(ssh_session session){
433
    /* register the packet callbacks */
434
0
    ssh_packet_set_callbacks(session, &ssh_dh_server_callbacks);
435
436
0
    ssh_dh_init_common(session->next_crypto);
437
0
}
438
439
/** @internal
440
 * @brief processes a SSH_MSG_KEXDH_INIT or SSH_MSG_KEX_DH_GEX_INIT packet and sends
441
 * the appropriate SSH_MSG_KEXDH_REPLY or SSH_MSG_KEX_DH_GEX_REPLY
442
 */
443
int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet)
444
0
{
445
0
    struct ssh_crypto_struct *crypto = session->next_crypto;
446
0
    ssh_key privkey = NULL;
447
0
    enum ssh_digest_e digest = SSH_DIGEST_AUTO;
448
0
    ssh_string sig_blob = NULL;
449
0
    ssh_string pubkey_blob = NULL;
450
0
    bignum client_pubkey;
451
0
#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L
452
0
    const_bignum server_pubkey;
453
#else
454
    bignum server_pubkey = NULL;
455
#endif /* OPENSSL_VERSION_NUMBER */
456
0
    int packet_type;
457
0
    int rc;
458
459
0
    rc = ssh_buffer_unpack(packet, "B", &client_pubkey);
460
0
    if (rc == SSH_ERROR) {
461
0
        ssh_set_error(session, SSH_FATAL, "No e number in client request");
462
0
        goto error;
463
0
    }
464
465
0
    rc = ssh_dh_keypair_set_keys(crypto->dh_ctx, DH_CLIENT_KEYPAIR,
466
0
                                 NULL, client_pubkey);
467
0
    if (rc != SSH_OK) {
468
0
        bignum_safe_free(client_pubkey);
469
0
        goto error;
470
0
    }
471
472
0
    rc = ssh_dh_keypair_gen_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR);
473
0
    if (rc == SSH_ERROR) {
474
0
        goto error;
475
0
    }
476
477
0
    rc = ssh_get_key_params(session, &privkey, &digest);
478
0
    if (rc != SSH_OK) {
479
0
        goto error;
480
0
    }
481
0
    rc = ssh_dh_compute_shared_secret(crypto->dh_ctx,
482
0
                                      DH_SERVER_KEYPAIR, DH_CLIENT_KEYPAIR,
483
0
                                      &crypto->shared_secret);
484
0
    ssh_dh_debug_crypto(crypto);
485
0
    if (rc == SSH_ERROR) {
486
0
        ssh_set_error(session, SSH_FATAL, "Could not generate shared secret");
487
0
        goto error;
488
0
    }
489
0
    rc = ssh_make_sessionid(session);
490
0
    if (rc != SSH_OK) {
491
0
        ssh_set_error(session, SSH_FATAL, "Could not create a session id");
492
0
        goto error;
493
0
    }
494
0
    sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest);
495
0
    if (sig_blob == NULL) {
496
0
        ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
497
0
        goto error;
498
0
    }
499
0
    switch (crypto->kex_type){
500
0
    case SSH_KEX_DH_GROUP1_SHA1:
501
0
    case SSH_KEX_DH_GROUP14_SHA1:
502
0
    case SSH_KEX_DH_GROUP14_SHA256:
503
0
    case SSH_KEX_DH_GROUP16_SHA512:
504
0
    case SSH_KEX_DH_GROUP18_SHA512:
505
0
        packet_type = SSH2_MSG_KEXDH_REPLY;
506
0
        break;
507
0
#ifdef WITH_GEX
508
0
    case SSH_KEX_DH_GEX_SHA1:
509
0
    case SSH_KEX_DH_GEX_SHA256:
510
0
        packet_type = SSH2_MSG_KEX_DH_GEX_REPLY;
511
0
        break;
512
0
#endif /* WITH_GEX */
513
0
    default:
514
0
        ssh_set_error(session, SSH_FATAL, "Invalid kex type");
515
0
        goto error;
516
0
    }
517
0
    rc = ssh_dh_keypair_get_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR,
518
0
                                 NULL, &server_pubkey);
519
0
    if (rc != SSH_OK){
520
0
        goto error;
521
0
    }
522
0
    rc = ssh_dh_get_next_server_publickey_blob(session, &pubkey_blob);
523
0
    if (rc != SSH_OK){
524
0
        ssh_set_error_oom(session);
525
0
        goto error;
526
0
    }
527
0
    rc = ssh_buffer_pack(session->out_buffer,
528
0
                         "bSBS",
529
0
                         packet_type,
530
0
                         pubkey_blob,
531
0
                         server_pubkey,
532
0
                         sig_blob);
533
0
    SSH_STRING_FREE(sig_blob);
534
0
    SSH_STRING_FREE(pubkey_blob);
535
#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L
536
    bignum_safe_free(server_pubkey);
537
#endif
538
0
    if(rc != SSH_OK) {
539
0
        ssh_set_error_oom(session);
540
0
        ssh_buffer_reinit(session->out_buffer);
541
0
        goto error;
542
0
    }
543
0
    rc = ssh_packet_send(session);
544
0
    if (rc == SSH_ERROR) {
545
0
        goto error;
546
0
    }
547
0
    SSH_LOG(SSH_LOG_DEBUG, "Sent KEX_DH_[GEX]_REPLY");
548
549
0
    if (ssh_buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
550
0
        ssh_buffer_reinit(session->out_buffer);
551
0
        goto error;
552
0
    }
553
0
    session->dh_handshake_state=DH_STATE_NEWKEYS_SENT;
554
0
    if (ssh_packet_send(session) == SSH_ERROR) {
555
0
        goto error;
556
0
    }
557
0
    SSH_LOG(SSH_LOG_PACKET, "SSH_MSG_NEWKEYS sent");
558
559
0
    return SSH_OK;
560
0
error:
561
0
    SSH_STRING_FREE(sig_blob);
562
0
    SSH_STRING_FREE(pubkey_blob);
563
#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L
564
    bignum_safe_free(server_pubkey);
565
#endif
566
567
0
    session->session_state = SSH_SESSION_STATE_ERROR;
568
0
    ssh_dh_cleanup(session->next_crypto);
569
0
    return SSH_ERROR;
570
0
}
571
572
/** @internal
573
 * @brief parse an incoming SSH_MSG_KEXDH_INIT packet and complete
574
 *        Diffie-Hellman key exchange
575
 **/
576
0
static SSH_PACKET_CALLBACK(ssh_packet_server_dh_init){
577
0
    (void)type;
578
0
    (void)user;
579
0
    SSH_LOG(SSH_LOG_DEBUG, "Received SSH_MSG_KEXDH_INIT");
580
0
    ssh_packet_remove_callbacks(session, &ssh_dh_server_callbacks);
581
0
    ssh_server_dh_process_init(session, packet);
582
0
    return SSH_PACKET_USED;
583
0
}
584
585
/** @internal
586
 * @brief Choose a fallback group for the DH Group exchange if the
587
 * moduli file is not readable
588
 * @param[in] pmax maximum requestsd group size
589
 * @param[out] modulus
590
 * @param[out] generator
591
 * @returns SSH_OK on success, SSH_ERROR otherwise
592
 */
593
int ssh_fallback_group(uint32_t pmax,
594
                       bignum *modulus,
595
                       bignum *generator)
596
0
{
597
0
    *modulus = NULL;
598
0
    *generator = NULL;
599
600
0
    if (pmax < 3072) {
601
0
        bignum_dup(ssh_dh_group14, modulus);
602
0
    } else if (pmax < 6144) {
603
0
        bignum_dup(ssh_dh_group16, modulus);
604
0
    } else {
605
0
        bignum_dup(ssh_dh_group18, modulus);
606
0
    }
607
0
    if (*modulus == NULL) {
608
0
        return SSH_ERROR;
609
0
    }
610
611
0
    bignum_dup(ssh_dh_generator, generator);
612
0
    if (*generator == NULL) {
613
0
        bignum_safe_free((*modulus));
614
0
        return SSH_ERROR;
615
0
    }
616
617
0
    return SSH_OK;
618
0
}
619
620
#endif /* WITH_SERVER */
621
622
/**
623
 * @addtogroup libssh_session
624
 *
625
 * @{
626
 */
627
628
bool ssh_dh_is_known_group(bignum modulus, bignum generator)
629
0
{
630
0
    int cmp, bits;
631
0
    bignum m = NULL;
632
633
0
    bits = bignum_num_bits(modulus);
634
0
    if (bits < 3072) {
635
0
        m = ssh_dh_group14;
636
0
    } else if (bits < 6144) {
637
0
        m = ssh_dh_group16;
638
0
    } else {
639
0
        m = ssh_dh_group18;
640
0
    }
641
642
0
    cmp = bignum_cmp(m, modulus);
643
0
    if (cmp != 0) {
644
0
        return false;
645
0
    }
646
647
0
    cmp = bignum_cmp(ssh_dh_generator, generator);
648
0
    if (cmp != 0) {
649
0
        return false;
650
0
    }
651
652
0
    SSH_LOG(SSH_LOG_TRACE, "The received primes in FIPS are known");
653
0
    return true;
654
0
}
655
656
ssh_key ssh_dh_get_current_server_publickey(ssh_session session)
657
0
{
658
0
    if (session->current_crypto == NULL) {
659
0
        return NULL;
660
0
    }
661
662
0
    return session->current_crypto->server_pubkey;
663
0
}
664
665
/* Caller needs to free the blob */
666
int ssh_dh_get_current_server_publickey_blob(ssh_session session,
667
                                     ssh_string *pubkey_blob)
668
0
{
669
0
    const ssh_key pubkey = ssh_dh_get_current_server_publickey(session);
670
671
0
    return ssh_pki_export_pubkey_blob(pubkey, pubkey_blob);
672
0
}
673
674
ssh_key ssh_dh_get_next_server_publickey(ssh_session session)
675
0
{
676
0
    return session->next_crypto->server_pubkey;
677
0
}
678
679
/* Caller needs to free the blob */
680
int ssh_dh_get_next_server_publickey_blob(ssh_session session,
681
                                          ssh_string *pubkey_blob)
682
0
{
683
0
    const ssh_key pubkey = ssh_dh_get_next_server_publickey(session);
684
685
0
    return ssh_pki_export_pubkey_blob(pubkey, pubkey_blob);
686
0
}
687
688
/**
689
 * @internal
690
 *
691
 * @brief Convert a buffer into an unpadded base64 string.
692
 * The caller has to free the memory.
693
 *
694
 * @param  hash         What should be converted to a base64 string.
695
 *
696
 * @param  len          Length of the buffer to convert.
697
 *
698
 * @return              The base64 string or NULL on error.
699
 *
700
 * @see ssh_string_free_char()
701
 */
702
static char *ssh_get_b64_unpadded(const unsigned char *hash, size_t len)
703
0
{
704
0
    char *b64_padded = NULL;
705
0
    char *b64_unpadded = NULL;
706
0
    size_t k;
707
708
0
    b64_padded = (char *)bin_to_base64(hash, len);
709
0
    if (b64_padded == NULL) {
710
0
        return NULL;
711
0
    }
712
0
    for (k = strlen(b64_padded); k != 0 && b64_padded[k-1] == '='; k--);
713
714
0
    b64_unpadded = strndup(b64_padded, k);
715
0
    SAFE_FREE(b64_padded);
716
717
0
    return b64_unpadded;
718
0
}
719
720
/**
721
 * @brief Get a hash as a human-readable hex- or base64-string.
722
 *
723
 * This gets an allocated fingerprint hash.  If it is a SHA sum, it will
724
 * return an unpadded base64 string.  If it is a MD5 sum, it will return a hex
725
 * string. Either way, the output is prepended by the hash-type.
726
 *
727
 * @warning Do NOT use MD5 or SHA1! Those hash functions are being deprecated.
728
 *
729
 * @param  type         Which sort of hash is given, use
730
 *                      SSH_PUBLICKEY_HASH_SHA256 or better.
731
 *
732
 * @param  hash         The hash to be converted to fingerprint.
733
 *
734
 * @param  len          Length of the buffer to convert.
735
 *
736
 * @return Returns the allocated fingerprint hash or NULL on error. The caller
737
 *         needs to free the memory using ssh_string_free_char().
738
 *
739
 * @see ssh_string_free_char()
740
 */
741
char *ssh_get_fingerprint_hash(enum ssh_publickey_hash_type type,
742
                               unsigned char *hash,
743
                               size_t len)
744
0
{
745
0
    const char *prefix = "UNKNOWN";
746
0
    char *fingerprint = NULL;
747
0
    char *str = NULL;
748
0
    size_t str_len;
749
0
    int rc;
750
751
0
    switch (type) {
752
0
    case SSH_PUBLICKEY_HASH_SHA1:
753
0
    case SSH_PUBLICKEY_HASH_SHA256:
754
0
        fingerprint = ssh_get_b64_unpadded(hash, len);
755
0
        break;
756
0
    case SSH_PUBLICKEY_HASH_MD5:
757
0
        fingerprint = ssh_get_hexa(hash, len);
758
0
        break;
759
0
    }
760
0
    if (fingerprint == NULL) {
761
0
        return NULL;
762
0
    }
763
764
0
    switch (type) {
765
0
    case SSH_PUBLICKEY_HASH_MD5:
766
0
        prefix = "MD5";
767
0
        break;
768
0
    case SSH_PUBLICKEY_HASH_SHA1:
769
0
        prefix = "SHA1";
770
0
        break;
771
0
    case SSH_PUBLICKEY_HASH_SHA256:
772
0
        prefix = "SHA256";
773
0
        break;
774
0
    }
775
776
0
    str_len = strlen(prefix);
777
0
    if (str_len + 1 + strlen(fingerprint) + 1 < str_len) {
778
0
        SAFE_FREE(fingerprint);
779
0
        return NULL;
780
0
    }
781
0
    str_len += 1 + strlen(fingerprint) + 1;
782
783
0
    str = malloc(str_len);
784
0
    if (str == NULL) {
785
0
        SAFE_FREE(fingerprint);
786
0
        return NULL;
787
0
    }
788
0
    rc = snprintf(str, str_len, "%s:%s", prefix, fingerprint);
789
0
    SAFE_FREE(fingerprint);
790
0
    if (rc < 0 || rc < (int)(str_len - 1)) {
791
0
        SAFE_FREE(str);
792
0
    }
793
794
0
    return str;
795
0
}
796
797
/**
798
 * @brief Print a hash as a human-readable hex- or base64-string.
799
 *
800
 * This prints an unpadded base64 strings for SHA sums and hex strings for MD5
801
 * sum.  Either way, the output is prepended by the hash-type.
802
 *
803
 * @param  type         Which sort of hash is given. Use
804
 *                      SSH_PUBLICKEY_HASH_SHA256 or better.
805
 *
806
 * @param  hash         The hash to be converted to fingerprint.
807
 *
808
 * @param  len          Length of the buffer to convert.
809
 *
810
 * @see ssh_get_publickey_hash()
811
 * @see ssh_get_fingerprint_hash()
812
 */
813
void ssh_print_hash(enum ssh_publickey_hash_type type,
814
                    unsigned char *hash,
815
                    size_t len)
816
0
{
817
0
    char *fingerprint = NULL;
818
819
0
    fingerprint = ssh_get_fingerprint_hash(type,
820
0
                                           hash,
821
0
                                           len);
822
0
    if (fingerprint == NULL) {
823
0
        return;
824
0
    }
825
826
0
    fprintf(stderr, "%s\n", fingerprint);
827
828
0
    SAFE_FREE(fingerprint);
829
0
}
830
831
/** @} */