Coverage Report

Created: 2025-11-24 06:19

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
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
void ssh_client_dh_remove_callbacks(ssh_session session)
358
0
{
359
0
    ssh_packet_remove_callbacks(session, &ssh_dh_client_callbacks);
360
0
}
361
362
0
SSH_PACKET_CALLBACK(ssh_packet_client_dh_reply){
363
0
  struct ssh_crypto_struct *crypto=session->next_crypto;
364
0
  ssh_string pubkey_blob = NULL;
365
0
  bignum server_pubkey;
366
0
  int rc;
367
368
0
  (void)type;
369
0
  (void)user;
370
371
0
  ssh_client_dh_remove_callbacks(session);
372
373
0
  rc = ssh_buffer_unpack(packet, "SBS", &pubkey_blob, &server_pubkey,
374
0
          &crypto->dh_server_signature);
375
0
  if (rc == SSH_ERROR) {
376
0
      goto error;
377
0
  }
378
0
  rc = ssh_dh_keypair_set_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR,
379
0
                               NULL, server_pubkey);
380
0
  if (rc != SSH_OK) {
381
0
      SSH_STRING_FREE(pubkey_blob);
382
0
      bignum_safe_free(server_pubkey);
383
0
      goto error;
384
0
  }
385
0
  rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob);
386
0
  SSH_STRING_FREE(pubkey_blob);
387
0
  if (rc != 0) {
388
0
      goto error;
389
0
  }
390
391
0
  rc = ssh_dh_compute_shared_secret(session->next_crypto->dh_ctx,
392
0
                                    DH_CLIENT_KEYPAIR, DH_SERVER_KEYPAIR,
393
0
                                    &session->next_crypto->shared_secret);
394
0
  ssh_dh_debug_crypto(session->next_crypto);
395
0
  if (rc == SSH_ERROR){
396
0
    ssh_set_error(session, SSH_FATAL, "Could not generate shared secret");
397
0
    goto error;
398
0
  }
399
400
  /* Send the MSG_NEWKEYS */
401
0
  rc = ssh_packet_send_newkeys(session);
402
0
  if (rc == SSH_ERROR) {
403
0
    goto error;
404
0
  }
405
0
  session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
406
0
  return SSH_PACKET_USED;
407
0
error:
408
0
  ssh_dh_cleanup(session->next_crypto);
409
0
  session->session_state=SSH_SESSION_STATE_ERROR;
410
0
  return SSH_PACKET_USED;
411
0
}
412
413
#ifdef WITH_SERVER
414
415
static SSH_PACKET_CALLBACK(ssh_packet_server_dh_init);
416
417
static ssh_packet_callback dh_server_callbacks[] = {
418
    ssh_packet_server_dh_init,
419
};
420
421
static struct ssh_packet_callbacks_struct ssh_dh_server_callbacks = {
422
    .start = SSH2_MSG_KEXDH_INIT,
423
    .n_callbacks = 1,
424
    .callbacks = dh_server_callbacks,
425
    .user = NULL
426
};
427
428
/** @internal
429
 * @brief sets up the diffie-hellman-groupx kex callbacks
430
 */
431
0
void ssh_server_dh_init(ssh_session session){
432
    /* register the packet callbacks */
433
0
    ssh_packet_set_callbacks(session, &ssh_dh_server_callbacks);
434
435
0
    ssh_dh_init_common(session->next_crypto);
436
0
}
437
438
/** @internal
439
 * @brief processes a SSH_MSG_KEXDH_INIT or SSH_MSG_KEX_DH_GEX_INIT packet and sends
440
 * the appropriate SSH_MSG_KEXDH_REPLY or SSH_MSG_KEX_DH_GEX_REPLY
441
 */
442
int ssh_server_dh_process_init(ssh_session session, ssh_buffer packet)
443
0
{
444
0
    struct ssh_crypto_struct *crypto = session->next_crypto;
445
0
    ssh_key privkey = NULL;
446
0
    enum ssh_digest_e digest = SSH_DIGEST_AUTO;
447
0
    ssh_string sig_blob = NULL;
448
0
    ssh_string pubkey_blob = NULL;
449
0
    bignum client_pubkey;
450
0
#if !defined(HAVE_LIBCRYPTO) || OPENSSL_VERSION_NUMBER < 0x30000000L
451
0
    const_bignum server_pubkey;
452
#else
453
    bignum server_pubkey = NULL;
454
#endif /* OPENSSL_VERSION_NUMBER */
455
0
    int packet_type;
456
0
    int rc;
457
458
0
    rc = ssh_buffer_unpack(packet, "B", &client_pubkey);
459
0
    if (rc == SSH_ERROR) {
460
0
        ssh_set_error(session, SSH_FATAL, "No e number in client request");
461
0
        goto error;
462
0
    }
463
464
0
    rc = ssh_dh_keypair_set_keys(crypto->dh_ctx, DH_CLIENT_KEYPAIR,
465
0
                                 NULL, client_pubkey);
466
0
    if (rc != SSH_OK) {
467
0
        bignum_safe_free(client_pubkey);
468
0
        goto error;
469
0
    }
470
471
0
    rc = ssh_dh_keypair_gen_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR);
472
0
    if (rc == SSH_ERROR) {
473
0
        goto error;
474
0
    }
475
476
0
    rc = ssh_get_key_params(session, &privkey, &digest);
477
0
    if (rc != SSH_OK) {
478
0
        goto error;
479
0
    }
480
0
    rc = ssh_dh_compute_shared_secret(crypto->dh_ctx,
481
0
                                      DH_SERVER_KEYPAIR, DH_CLIENT_KEYPAIR,
482
0
                                      &crypto->shared_secret);
483
0
    ssh_dh_debug_crypto(crypto);
484
0
    if (rc == SSH_ERROR) {
485
0
        ssh_set_error(session, SSH_FATAL, "Could not generate shared secret");
486
0
        goto error;
487
0
    }
488
0
    rc = ssh_make_sessionid(session);
489
0
    if (rc != SSH_OK) {
490
0
        ssh_set_error(session, SSH_FATAL, "Could not create a session id");
491
0
        goto error;
492
0
    }
493
0
    sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey, digest);
494
0
    if (sig_blob == NULL) {
495
0
        ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
496
0
        goto error;
497
0
    }
498
0
    switch (crypto->kex_type){
499
0
    case SSH_KEX_DH_GROUP1_SHA1:
500
0
    case SSH_KEX_DH_GROUP14_SHA1:
501
0
    case SSH_KEX_DH_GROUP14_SHA256:
502
0
    case SSH_KEX_DH_GROUP16_SHA512:
503
0
    case SSH_KEX_DH_GROUP18_SHA512:
504
0
        packet_type = SSH2_MSG_KEXDH_REPLY;
505
0
        break;
506
0
#ifdef WITH_GEX
507
0
    case SSH_KEX_DH_GEX_SHA1:
508
0
    case SSH_KEX_DH_GEX_SHA256:
509
0
        packet_type = SSH2_MSG_KEX_DH_GEX_REPLY;
510
0
        break;
511
0
#endif /* WITH_GEX */
512
0
    default:
513
0
        ssh_set_error(session, SSH_FATAL, "Invalid kex type");
514
0
        goto error;
515
0
    }
516
0
    rc = ssh_dh_keypair_get_keys(crypto->dh_ctx, DH_SERVER_KEYPAIR,
517
0
                                 NULL, &server_pubkey);
518
0
    if (rc != SSH_OK){
519
0
        goto error;
520
0
    }
521
0
    rc = ssh_dh_get_next_server_publickey_blob(session, &pubkey_blob);
522
0
    if (rc != SSH_OK){
523
0
        ssh_set_error_oom(session);
524
0
        goto error;
525
0
    }
526
0
    rc = ssh_buffer_pack(session->out_buffer,
527
0
                         "bSBS",
528
0
                         packet_type,
529
0
                         pubkey_blob,
530
0
                         server_pubkey,
531
0
                         sig_blob);
532
0
    SSH_STRING_FREE(sig_blob);
533
0
    SSH_STRING_FREE(pubkey_blob);
534
#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L
535
    bignum_safe_free(server_pubkey);
536
#endif
537
0
    if(rc != SSH_OK) {
538
0
        ssh_set_error_oom(session);
539
0
        ssh_buffer_reinit(session->out_buffer);
540
0
        goto error;
541
0
    }
542
0
    rc = ssh_packet_send(session);
543
0
    if (rc == SSH_ERROR) {
544
0
        goto error;
545
0
    }
546
0
    SSH_LOG(SSH_LOG_DEBUG, "Sent KEX_DH_[GEX]_REPLY");
547
548
0
    session->dh_handshake_state=DH_STATE_NEWKEYS_SENT;
549
    /* Send the MSG_NEWKEYS */
550
0
    rc = ssh_packet_send_newkeys(session);
551
0
    if (rc == SSH_ERROR) {
552
0
        goto error;
553
0
    }
554
555
0
    return SSH_OK;
556
0
error:
557
0
    SSH_STRING_FREE(sig_blob);
558
0
    SSH_STRING_FREE(pubkey_blob);
559
#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L
560
    bignum_safe_free(server_pubkey);
561
#endif
562
563
0
    session->session_state = SSH_SESSION_STATE_ERROR;
564
0
    ssh_dh_cleanup(session->next_crypto);
565
0
    return SSH_ERROR;
566
0
}
567
568
/** @internal
569
 * @brief parse an incoming SSH_MSG_KEXDH_INIT packet and complete
570
 *        Diffie-Hellman key exchange
571
 **/
572
0
static SSH_PACKET_CALLBACK(ssh_packet_server_dh_init){
573
0
    (void)type;
574
0
    (void)user;
575
0
    SSH_LOG(SSH_LOG_DEBUG, "Received SSH_MSG_KEXDH_INIT");
576
0
    ssh_packet_remove_callbacks(session, &ssh_dh_server_callbacks);
577
0
    ssh_server_dh_process_init(session, packet);
578
0
    return SSH_PACKET_USED;
579
0
}
580
581
/** @internal
582
 * @brief Choose a fallback group for the DH Group exchange if the
583
 * moduli file is not readable
584
 * @param[in] pmax maximum requestsd group size
585
 * @param[out] modulus
586
 * @param[out] generator
587
 * @returns SSH_OK on success, SSH_ERROR otherwise
588
 */
589
int ssh_fallback_group(uint32_t pmax,
590
                       bignum *modulus,
591
                       bignum *generator)
592
0
{
593
0
    *modulus = NULL;
594
0
    *generator = NULL;
595
596
0
    if (pmax < 3072) {
597
0
        bignum_dup(ssh_dh_group14, modulus);
598
0
    } else if (pmax < 6144) {
599
0
        bignum_dup(ssh_dh_group16, modulus);
600
0
    } else {
601
0
        bignum_dup(ssh_dh_group18, modulus);
602
0
    }
603
0
    if (*modulus == NULL) {
604
0
        return SSH_ERROR;
605
0
    }
606
607
0
    bignum_dup(ssh_dh_generator, generator);
608
0
    if (*generator == NULL) {
609
0
        bignum_safe_free((*modulus));
610
0
        return SSH_ERROR;
611
0
    }
612
613
0
    return SSH_OK;
614
0
}
615
616
#endif /* WITH_SERVER */
617
618
/**
619
 * @addtogroup libssh_session
620
 *
621
 * @{
622
 */
623
624
bool ssh_dh_is_known_group(bignum modulus, bignum generator)
625
0
{
626
0
    int cmp, bits;
627
0
    bignum m = NULL;
628
629
0
    bits = bignum_num_bits(modulus);
630
0
    if (bits < 3072) {
631
0
        m = ssh_dh_group14;
632
0
    } else if (bits < 6144) {
633
0
        m = ssh_dh_group16;
634
0
    } else {
635
0
        m = ssh_dh_group18;
636
0
    }
637
638
0
    cmp = bignum_cmp(m, modulus);
639
0
    if (cmp != 0) {
640
0
        return false;
641
0
    }
642
643
0
    cmp = bignum_cmp(ssh_dh_generator, generator);
644
0
    if (cmp != 0) {
645
0
        return false;
646
0
    }
647
648
0
    SSH_LOG(SSH_LOG_TRACE, "The received primes in FIPS are known");
649
0
    return true;
650
0
}
651
652
ssh_key ssh_dh_get_current_server_publickey(ssh_session session)
653
0
{
654
0
    if (session->current_crypto == NULL) {
655
0
        return NULL;
656
0
    }
657
658
0
    return session->current_crypto->server_pubkey;
659
0
}
660
661
/* Caller needs to free the blob */
662
int ssh_dh_get_current_server_publickey_blob(ssh_session session,
663
                                     ssh_string *pubkey_blob)
664
0
{
665
0
    const ssh_key pubkey = ssh_dh_get_current_server_publickey(session);
666
667
0
    return ssh_pki_export_pubkey_blob(pubkey, pubkey_blob);
668
0
}
669
670
ssh_key ssh_dh_get_next_server_publickey(ssh_session session)
671
0
{
672
0
    return session->next_crypto->server_pubkey;
673
0
}
674
675
/* Caller needs to free the blob */
676
int ssh_dh_get_next_server_publickey_blob(ssh_session session,
677
                                          ssh_string *pubkey_blob)
678
0
{
679
0
    const ssh_key pubkey = ssh_dh_get_next_server_publickey(session);
680
681
0
    return ssh_pki_export_pubkey_blob(pubkey, pubkey_blob);
682
0
}
683
684
/**
685
 * @internal
686
 *
687
 * @brief Convert a buffer into an unpadded base64 string.
688
 * The caller has to free the memory.
689
 *
690
 * @param  hash         What should be converted to a base64 string.
691
 *
692
 * @param  len          Length of the buffer to convert.
693
 *
694
 * @return              The base64 string or NULL on error.
695
 *
696
 * @see ssh_string_free_char()
697
 */
698
static char *ssh_get_b64_unpadded(const unsigned char *hash, size_t len)
699
0
{
700
0
    char *b64_padded = NULL;
701
0
    char *b64_unpadded = NULL;
702
0
    size_t k;
703
704
0
    b64_padded = (char *)bin_to_base64(hash, len);
705
0
    if (b64_padded == NULL) {
706
0
        return NULL;
707
0
    }
708
0
    for (k = strlen(b64_padded); k != 0 && b64_padded[k-1] == '='; k--);
709
710
0
    b64_unpadded = strndup(b64_padded, k);
711
0
    SAFE_FREE(b64_padded);
712
713
0
    return b64_unpadded;
714
0
}
715
716
/**
717
 * @brief Get a hash as a human-readable hex- or base64-string.
718
 *
719
 * This gets an allocated fingerprint hash.  If it is a SHA sum, it will
720
 * return an unpadded base64 string.  If it is a MD5 sum, it will return a hex
721
 * string. Either way, the output is prepended by the hash-type.
722
 *
723
 * @warning Do NOT use MD5 or SHA1! Those hash functions are being deprecated.
724
 *
725
 * @param  type         Which sort of hash is given, use
726
 *                      SSH_PUBLICKEY_HASH_SHA256 or better.
727
 *
728
 * @param  hash         The hash to be converted to fingerprint.
729
 *
730
 * @param  len          Length of the buffer to convert.
731
 *
732
 * @return Returns the allocated fingerprint hash or NULL on error. The caller
733
 *         needs to free the memory using ssh_string_free_char().
734
 *
735
 * @see ssh_string_free_char()
736
 */
737
char *ssh_get_fingerprint_hash(enum ssh_publickey_hash_type type,
738
                               unsigned char *hash,
739
                               size_t len)
740
0
{
741
0
    const char *prefix = "UNKNOWN";
742
0
    char *fingerprint = NULL;
743
0
    char *str = NULL;
744
0
    size_t str_len;
745
0
    int rc;
746
747
0
    switch (type) {
748
0
    case SSH_PUBLICKEY_HASH_SHA1:
749
0
    case SSH_PUBLICKEY_HASH_SHA256:
750
0
        fingerprint = ssh_get_b64_unpadded(hash, len);
751
0
        break;
752
0
    case SSH_PUBLICKEY_HASH_MD5:
753
0
        fingerprint = ssh_get_hexa(hash, len);
754
0
        break;
755
0
    }
756
0
    if (fingerprint == NULL) {
757
0
        return NULL;
758
0
    }
759
760
0
    switch (type) {
761
0
    case SSH_PUBLICKEY_HASH_MD5:
762
0
        prefix = "MD5";
763
0
        break;
764
0
    case SSH_PUBLICKEY_HASH_SHA1:
765
0
        prefix = "SHA1";
766
0
        break;
767
0
    case SSH_PUBLICKEY_HASH_SHA256:
768
0
        prefix = "SHA256";
769
0
        break;
770
0
    }
771
772
0
    str_len = strlen(prefix);
773
0
    if (str_len + 1 + strlen(fingerprint) + 1 < str_len) {
774
0
        SAFE_FREE(fingerprint);
775
0
        return NULL;
776
0
    }
777
0
    str_len += 1 + strlen(fingerprint) + 1;
778
779
0
    str = malloc(str_len);
780
0
    if (str == NULL) {
781
0
        SAFE_FREE(fingerprint);
782
0
        return NULL;
783
0
    }
784
0
    rc = snprintf(str, str_len, "%s:%s", prefix, fingerprint);
785
0
    SAFE_FREE(fingerprint);
786
0
    if (rc < 0 || rc < (int)(str_len - 1)) {
787
0
        SAFE_FREE(str);
788
0
    }
789
790
0
    return str;
791
0
}
792
793
/**
794
 * @brief Print a hash as a human-readable hex- or base64-string.
795
 *
796
 * This prints an unpadded base64 strings for SHA sums and hex strings for MD5
797
 * sum.  Either way, the output is prepended by the hash-type.
798
 *
799
 * @param  type         Which sort of hash is given. Use
800
 *                      SSH_PUBLICKEY_HASH_SHA256 or better.
801
 *
802
 * @param  hash         The hash to be converted to fingerprint.
803
 *
804
 * @param  len          Length of the buffer to convert.
805
 *
806
 * @see ssh_get_publickey_hash()
807
 * @see ssh_get_fingerprint_hash()
808
 */
809
void ssh_print_hash(enum ssh_publickey_hash_type type,
810
                    unsigned char *hash,
811
                    size_t len)
812
0
{
813
0
    char *fingerprint = NULL;
814
815
0
    fingerprint = ssh_get_fingerprint_hash(type,
816
0
                                           hash,
817
0
                                           len);
818
0
    if (fingerprint == NULL) {
819
0
        return;
820
0
    }
821
822
0
    fprintf(stderr, "%s\n", fingerprint);
823
824
    SAFE_FREE(fingerprint);
825
0
}
826
827
/** @} */