Coverage Report

Created: 2026-02-26 06:05

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