blob: e602dd3a2f5ffe9ad0bf1937d2780e9aa8620339 [file] [log] [blame]
Alexandre Lision51140e12013-12-02 10:54:09 -05001/*
2 Copyright (C) 2006, 2009 by Werner Dittmann
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18 * In addition, as a special exception, the copyright holders give
19 * permission to link the code of portions of this program with the
20 * OpenSSL library under certain conditions as described in each
21 * individual source file, and distribute linked combinations
22 * including the two.
23 * You must obey the GNU General Public License in all respects
24 * for all of the code used other than OpenSSL. If you modify
25 * file(s) with this exception, you may extend this exception to your
26 * version of the file(s), but you are not obligated to do so. If you
27 * do not wish to do so, delete this exception statement from your
28 * version. If you delete this exception statement from all source
29 * files in the program, then also delete it here.
30 */
31
32/** Copyright (C) 2006, 2009
33 *
34 * @author Werner Dittmann <Werner.Dittmann@t-online.de>
35 */
36
37#include <string.h>
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050038#include <sys/types.h>
39#include <sys/stat.h>
40#include <fcntl.h>
Alexandre Lision51140e12013-12-02 10:54:09 -050041
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050042#include <bn.h>
43#include <bnprint.h>
44#include <ec/ec.h>
45#include <ec/ecdh.h>
46#include <zrtp/crypto/zrtpDH.h>
47#include <zrtp/libzrtpcpp/ZrtpTextData.h>
48#include <cryptcommon/aes.h>
49#include <cryptcommon/ZrtpRandom.h>
Alexandre Lision51140e12013-12-02 10:54:09 -050050
Alexandre Lision51140e12013-12-02 10:54:09 -050051
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050052static BigNum bnP2048 = {0};
53static BigNum bnP3072 = {0};
Alexandre Lision51140e12013-12-02 10:54:09 -050054
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050055static BigNum bnP2048MinusOne = {0};
56static BigNum bnP3072MinusOne = {0};
Alexandre Lision51140e12013-12-02 10:54:09 -050057
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050058static BigNum two = {0};
Alexandre Lision51140e12013-12-02 10:54:09 -050059
60static uint8_t dhinit = 0;
61
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050062typedef struct _dhCtx {
63 BigNum privKey;
64 BigNum pubKey;
Alexandre Lisionddd731e2014-01-31 11:50:08 -050065 NistECpCurve curve;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050066 EcPoint pubPoint;
67} dhCtx;
68
Alexandre Lision51140e12013-12-02 10:54:09 -050069void randomZRTP(uint8_t *buf, int32_t length)
70{
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050071 ZrtpRandom::getRandomData(buf, length);
Alexandre Lision51140e12013-12-02 10:54:09 -050072}
73
74static const uint8_t P2048[] =
75{
76 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
77 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
78 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
79 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
80 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
81 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
82 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
83 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
84 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
85 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
86 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
87 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
88 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
89 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
90 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
91 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
92 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
93 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
94 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
95 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
96 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF,
97 0xFF, 0xFF, 0xFF, 0xFF
98};
99
100static const uint8_t P3072[] =
101{
102 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
103 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
104 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
105 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
106 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
107 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
108 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
109 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
110 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
111 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
112 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
113 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
114 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
115 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
116 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
117 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
118 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
119 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
120 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
121 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
122 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
123 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
124 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
125 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
126 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
127 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
128 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
129 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
130 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
131 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
132 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
133 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
134};
135
136/* **************
137static const uint8_t P4096[] =
138{
1390xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
1400x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
1410x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
1420x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
1430xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
1440xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
1450xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
1460xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
1470xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
1480x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
1490xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
1500x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
1510x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
1520x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
1530x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
1540xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
1550xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
1560xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
1570xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
1580xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
1590x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
1600x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
1610xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
1620x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
1630xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
1640x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
1650xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
1660x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
1670xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
1680xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
1690x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
1700xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
1710x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
1720x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
1730x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
1740x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
1750x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
1760xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
1770x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
1780x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
1790x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
1800x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
1810xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
182};
183*************** */
184
185ZrtpDH::ZrtpDH(const char* type) {
186
187 uint8_t random[64];
188
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500189 ctx = static_cast<void*>(new dhCtx);
190 dhCtx* tmpCtx = static_cast<dhCtx*>(ctx);
191
Alexandre Lision51140e12013-12-02 10:54:09 -0500192 // Well - the algo type is only 4 char thus cast to int32 and compare
193 if (*(int32_t*)type == *(int32_t*)dh2k) {
194 pkType = DH2K;
195 }
196 else if (*(int32_t*)type == *(int32_t*)dh3k) {
197 pkType = DH3K;
198 }
199 else if (*(int32_t*)type == *(int32_t*)ec25) {
200 pkType = EC25;
201 }
202 else if (*(int32_t*)type == *(int32_t*)ec38) {
203 pkType = EC38;
204 }
205 else {
206 return;
207 }
208
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500209 randomZRTP(random, sizeof(random));
Alexandre Lision51140e12013-12-02 10:54:09 -0500210
211 if (!dhinit) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500212 bnBegin(&two);
213 bnSetQ(&two, 2);
Alexandre Lision51140e12013-12-02 10:54:09 -0500214
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500215 bnBegin(&bnP2048);
216 bnInsertBigBytes(&bnP2048, P2048, 0, sizeof(P2048));
217 bnBegin(&bnP3072);
218 bnInsertBigBytes(&bnP3072, P3072, 0, sizeof(P3072));
Alexandre Lision51140e12013-12-02 10:54:09 -0500219
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500220 bnBegin(&bnP2048MinusOne);
221 bnCopy(&bnP2048MinusOne, &bnP2048);
222 bnSubQ(&bnP2048MinusOne, 1);
Alexandre Lision51140e12013-12-02 10:54:09 -0500223
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500224 bnBegin(&bnP3072MinusOne);
225 bnCopy(&bnP3072MinusOne, &bnP3072);
226 bnSubQ(&bnP3072MinusOne, 1);
227
Alexandre Lision51140e12013-12-02 10:54:09 -0500228 dhinit = 1;
229 }
230
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500231 bnBegin(&tmpCtx->privKey);
232 INIT_EC_POINT(&tmpCtx->pubPoint);
233
Alexandre Lision51140e12013-12-02 10:54:09 -0500234 switch (pkType) {
235 case DH2K:
236 case DH3K:
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500237 bnInsertBigBytes(&tmpCtx->privKey, random, 0, 256/8);
Alexandre Lision51140e12013-12-02 10:54:09 -0500238 break;
239
240 case EC25:
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500241 ecGetCurveNistECp(NIST256P, &tmpCtx->curve);
242 ecGenerateRandomNumber(&tmpCtx->curve, &tmpCtx->privKey);
Alexandre Lision51140e12013-12-02 10:54:09 -0500243 break;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500244
Alexandre Lision51140e12013-12-02 10:54:09 -0500245 case EC38:
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500246 ecGetCurveNistECp(NIST384P, &tmpCtx->curve);
247 ecGenerateRandomNumber(&tmpCtx->curve, &tmpCtx->privKey);
248 break;
Alexandre Lision51140e12013-12-02 10:54:09 -0500249 }
250}
251
252ZrtpDH::~ZrtpDH() {
253 if (ctx == NULL)
254 return;
255
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500256 dhCtx* tmpCtx = static_cast<dhCtx*>(ctx);
257 FREE_EC_POINT(&tmpCtx->pubPoint);
258 bnEnd(&tmpCtx->privKey);
259
Alexandre Lision51140e12013-12-02 10:54:09 -0500260 switch (pkType) {
261 case DH2K:
262 case DH3K:
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500263 bnEnd(&tmpCtx->pubKey);
Alexandre Lision51140e12013-12-02 10:54:09 -0500264 break;
265
266 case EC25:
267 case EC38:
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500268 ecFreeCurveNistECp(&tmpCtx->curve);
269 break;
Alexandre Lision51140e12013-12-02 10:54:09 -0500270 }
271}
272
273int32_t ZrtpDH::computeSecretKey(uint8_t *pubKeyBytes, uint8_t *secret) {
274
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500275 dhCtx* tmpCtx = static_cast<dhCtx*>(ctx);
276
277 int32_t length = getDhSize();
278
279 BigNum sec;
Alexandre Lision51140e12013-12-02 10:54:09 -0500280 if (pkType == DH2K || pkType == DH3K) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500281 BigNum pubKeyOther;
282 bnBegin(&pubKeyOther);
283 bnBegin(&sec);
Alexandre Lision51140e12013-12-02 10:54:09 -0500284
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500285 bnInsertBigBytes(&pubKeyOther, pubKeyBytes, 0, length);
286
287 if (pkType == DH2K) {
288 bnExpMod(&sec, &pubKeyOther, &tmpCtx->privKey, &bnP2048);
Alexandre Lision51140e12013-12-02 10:54:09 -0500289 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500290 else if (pkType == DH3K) {
291 bnExpMod(&sec, &pubKeyOther, &tmpCtx->privKey, &bnP3072);
292 }
293 else {
294 return 0;
295 }
296 bnEnd(&pubKeyOther);
297 bnExtractBigBytes(&sec, secret, 0, length);
298 bnEnd(&sec);
Alexandre Lision51140e12013-12-02 10:54:09 -0500299
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500300 return length;
301 }
302
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500303 if (pkType == EC25 || pkType == EC38) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500304 int32_t len = getPubKeySize() / 2;
305 EcPoint pub;
306
307 bnBegin(&sec);
308 INIT_EC_POINT(&pub);
309 bnSetQ(pub.z, 1); // initialze Z to one, these are affine coords
310
311 bnInsertBigBytes(pub.x, pubKeyBytes, 0, len);
312 bnInsertBigBytes(pub.y, pubKeyBytes+len, 0, len);
313
314 /* Generate agreement for responder: sec = pub * privKey */
315 ecdhComputeAgreement(&tmpCtx->curve, &sec, &pub, &tmpCtx->privKey);
316 bnExtractBigBytes(&sec, secret, 0, length);
317 bnEnd(&sec);
318 FREE_EC_POINT(&pub);
319
320 return length;
321 }
Alexandre Lision51140e12013-12-02 10:54:09 -0500322 return -1;
323}
324
325int32_t ZrtpDH::generatePublicKey()
326{
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500327 dhCtx* tmpCtx = static_cast<dhCtx*>(ctx);
Alexandre Lision51140e12013-12-02 10:54:09 -0500328
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500329 bnBegin(&tmpCtx->pubKey);
330 switch (pkType) {
331 case DH2K:
332 bnExpMod(&tmpCtx->pubKey, &two, &tmpCtx->privKey, &bnP2048);
333 break;
334
335 case DH3K:
336 bnExpMod(&tmpCtx->pubKey, &two, &tmpCtx->privKey, &bnP3072);
337 break;
338
339 case EC25:
340 case EC38:
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500341 return ecdhGeneratePublic(&tmpCtx->curve, &tmpCtx->pubPoint, &tmpCtx->privKey);
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500342 }
Alexandre Lision51140e12013-12-02 10:54:09 -0500343 return 0;
344}
345
346int32_t ZrtpDH::getDhSize() const
347{
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500348 switch (pkType) {
349 case DH2K:
350 return 2048/8;
351 break;
352 case DH3K:
353 return 3072/8;
354 break;
Alexandre Lision51140e12013-12-02 10:54:09 -0500355
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500356 case EC25:
Alexandre Lision51140e12013-12-02 10:54:09 -0500357 return 32;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500358 break;
359 case EC38:
Alexandre Lision51140e12013-12-02 10:54:09 -0500360 return 48;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500361 break;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500362 }
Alexandre Lision51140e12013-12-02 10:54:09 -0500363 return 0;
364}
365
366int32_t ZrtpDH::getPubKeySize() const
367{
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500368 dhCtx* tmpCtx = static_cast<dhCtx*>(ctx);
Alexandre Lision51140e12013-12-02 10:54:09 -0500369 if (pkType == DH2K || pkType == DH3K)
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500370 return bnBytes(&tmpCtx->pubKey);
Alexandre Lision51140e12013-12-02 10:54:09 -0500371
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500372 if (pkType == EC25 || pkType == EC38)
373 return bnBytes(tmpCtx->curve.p) * 2;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500374
Alexandre Lision51140e12013-12-02 10:54:09 -0500375 return 0;
376
377}
378
379int32_t ZrtpDH::getPubKeyBytes(uint8_t *buf) const
380{
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500381 dhCtx* tmpCtx = static_cast<dhCtx*>(ctx);
Alexandre Lision51140e12013-12-02 10:54:09 -0500382
383 if (pkType == DH2K || pkType == DH3K) {
384 // get len of pub_key, prepend with zeros to DH size
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500385 int size = getPubKeySize();
386 int32_t prepend = getDhSize() - size;
Alexandre Lision51140e12013-12-02 10:54:09 -0500387 if (prepend > 0) {
388 memset(buf, 0, prepend);
389 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500390 bnExtractBigBytes(&tmpCtx->pubKey, buf + prepend, 0, size);
391 return size;
Alexandre Lision51140e12013-12-02 10:54:09 -0500392 }
Alexandre Lision51140e12013-12-02 10:54:09 -0500393
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500394 if (pkType == EC25 || pkType == EC38) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500395 int32_t len = getPubKeySize() / 2;
396
397 bnExtractBigBytes(tmpCtx->pubPoint.x, buf, 0, len);
398 bnExtractBigBytes(tmpCtx->pubPoint.y, buf+len, 0, len);
399 return len * 2;
400 }
Alexandre Lision51140e12013-12-02 10:54:09 -0500401 return 0;
402}
403
404int32_t ZrtpDH::checkPubKey(uint8_t *pubKeyBytes) const
405{
Alexandre Lision51140e12013-12-02 10:54:09 -0500406
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500407 /* ECC validation (partial), NIST SP800-56A, section 5.6.2.6 */
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500408 if (pkType == EC25 || pkType == EC38) {
Alexandre Lision51140e12013-12-02 10:54:09 -0500409
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500410 struct BigNum t1, t2;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500411 dhCtx* tmpCtx = static_cast<dhCtx*>(ctx);
412 EcPoint pub;
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500413 int ret = 0;
Alexandre Lision51140e12013-12-02 10:54:09 -0500414
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500415 INIT_EC_POINT(&pub);
416 int32_t len = getPubKeySize() / 2;
417
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500418 bnBegin(&t1);
419 bnBegin(&t2);
420
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500421 bnInsertBigBytes(pub.x, pubKeyBytes, 0, len);
422 bnInsertBigBytes(pub.y, pubKeyBytes+len, 0, len);
423
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500424 /* Represent point at infinity by (0, 0), make sure it's not that */
425 if (bnCmpQ(pub.x, 0) == 0 && bnCmpQ(pub.y, 0) == 0) {
426 goto fail;
427 }
428 /* Check that coordinates are within range */
429 if (bnCmpQ(pub.x, 0) < 0 || bnCmp(pub.x, tmpCtx->curve.p) >= 0) {
430 goto fail;
431 }
432 if (bnCmpQ(pub.y, 0) < 0 || bnCmp(pub.y, tmpCtx->curve.p) >= 0) {
433 goto fail;
434 }
435 /* Check that point satisfies EC equation y^2 = x^3 - 3x + b, mod P */
436 bnSquareMod_(&t1, pub.y, tmpCtx->curve.p);
437 bnSquareMod_(&t2, pub.x, tmpCtx->curve.p);
438 bnSubQMod_(&t2, 3, tmpCtx->curve.p);
439 bnMulMod_(&t2, &t2, pub.x, tmpCtx->curve.p);
440 bnAddMod_(&t2, tmpCtx->curve.b, tmpCtx->curve.p);
441 if (bnCmp (&t1, &t2) != 0) {
442 goto fail;
443 }
444 ret = 1;
Alexandre Lision51140e12013-12-02 10:54:09 -0500445
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500446 fail:
447 FREE_EC_POINT(&pub);
448 bnEnd(&t1);
449 bnEnd(&t2);
450 return ret;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500451 }
452
453 BigNum pubKeyOther;
454 bnBegin(&pubKeyOther);
455 bnInsertBigBytes(&pubKeyOther, pubKeyBytes, 0, getDhSize());
Alexandre Lision51140e12013-12-02 10:54:09 -0500456
457 if (pkType == DH2K) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500458 if (bnCmp(&bnP2048MinusOne, &pubKeyOther) == 0) {
Alexandre Lision51140e12013-12-02 10:54:09 -0500459 return 0;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500460 }
Alexandre Lision51140e12013-12-02 10:54:09 -0500461 }
462 else if (pkType == DH3K) {
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500463 if (bnCmp(&bnP3072MinusOne, &pubKeyOther) == 0) {
Alexandre Lision51140e12013-12-02 10:54:09 -0500464 return 0;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500465
466 }
Alexandre Lision51140e12013-12-02 10:54:09 -0500467 }
468 else {
Alexandre Lision51140e12013-12-02 10:54:09 -0500469 return 0;
470 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500471 if (bnCmpQ(&pubKeyOther, 1) == 0) {
Alexandre Lision51140e12013-12-02 10:54:09 -0500472 return 0;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500473 }
Alexandre Lision51140e12013-12-02 10:54:09 -0500474
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500475 bnEnd(&pubKeyOther);
Alexandre Lision51140e12013-12-02 10:54:09 -0500476 return 1;
477}
478
479const char* ZrtpDH::getDHtype()
480{
481 switch (pkType) {
482 case DH2K:
483 return dh2k;
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500484 break;
Alexandre Lision51140e12013-12-02 10:54:09 -0500485 case DH3K:
486 return dh3k;
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500487 break;
Alexandre Lision51140e12013-12-02 10:54:09 -0500488 case EC25:
489 return ec25;
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500490 break;
Alexandre Lision51140e12013-12-02 10:54:09 -0500491 case EC38:
492 return ec38;
Alexandre Lisionddd731e2014-01-31 11:50:08 -0500493 break;
Alexandre Lision51140e12013-12-02 10:54:09 -0500494 }
495 return NULL;
496}
497
498/** EMACS **
499 * Local variables:
500 * mode: c++
501 * c-default-style: ellemtel
502 * c-basic-offset: 4
503 * End:
504 */