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