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