blob: bc885ef18f0a8fbff57c5280d99190b6f5ece08c [file] [log] [blame]
Alexandre Lision51140e12013-12-02 10:54:09 -05001/*
Alexandre Lision907ed2e2014-02-04 10:33:09 -05002 Copyright (C) 2006-2013 Werner Dittmann
Alexandre Lision51140e12013-12-02 10:54:09 -05003
4 This program is free software: you can redistribute it and/or modify
Alexandre Lision907ed2e2014-02-04 10:33:09 -05005 it under the terms of the GNU Lesser General Public License as published by
Alexandre Lision51140e12013-12-02 10:54:09 -05006 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program 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
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18/*
19 * Authors: Werner Dittmann <Werner.Dittmann@t-online.de>
20 */
21
Alexandre Lision907ed2e2014-02-04 10:33:09 -050022#include <ctype.h>
Alexandre Lision51140e12013-12-02 10:54:09 -050023#include <libzrtpcpp/ZrtpPacketHello.h>
24
25
26ZrtpPacketHello::ZrtpPacketHello() {
27 DEBUGOUT((fprintf(stdout, "Creating Hello packet without data\n")));
28}
29
30void ZrtpPacketHello::configureHello(ZrtpConfigure* config) {
31 // The NumSupported* data is in ZrtpTextData.h
32 nHash = config->getNumConfiguredAlgos(HashAlgorithm);
33 nCipher = config->getNumConfiguredAlgos(CipherAlgorithm);
34 nPubkey = config->getNumConfiguredAlgos(PubKeyAlgorithm);
35 nSas = config->getNumConfiguredAlgos(SasType);
36 nAuth = config->getNumConfiguredAlgos(AuthLength);
37
38 // length is fixed Header plus HMAC size (2*ZRTP_WORD_SIZE)
39 int32_t length = sizeof(HelloPacket_t) + (2 * ZRTP_WORD_SIZE);
40 length += nHash * ZRTP_WORD_SIZE;
41 length += nCipher * ZRTP_WORD_SIZE;
42 length += nPubkey * ZRTP_WORD_SIZE;
43 length += nSas * ZRTP_WORD_SIZE;
44 length += nAuth * ZRTP_WORD_SIZE;
45
46 // Don't change order of this sequence
47 oHash = sizeof(Hello_t);
48 oCipher = oHash + (nHash * ZRTP_WORD_SIZE);
49 oAuth = oCipher + (nCipher * ZRTP_WORD_SIZE);
50 oPubkey = oAuth + (nAuth * ZRTP_WORD_SIZE);
51 oSas = oPubkey + (nPubkey * ZRTP_WORD_SIZE);
52 oHmac = oSas + (nSas * ZRTP_WORD_SIZE); // offset to HMAC
53
54 void* allocated = &data;
55 memset(allocated, 0, sizeof(data));
56
57 zrtpHeader = (zrtpPacketHeader_t *)&((HelloPacket_t *)allocated)->hdr; // the standard header
58 helloHeader = (Hello_t *)&((HelloPacket_t *)allocated)->hello;
59
60 setZrtpId();
61
62 // minus 1 for CRC size
63 setLength(length / ZRTP_WORD_SIZE);
64 setMessageType((uint8_t*)HelloMsg);
65
Alexandre Lision51140e12013-12-02 10:54:09 -050066 uint32_t lenField = nHash << 16;
67 for (int32_t i = 0; i < nHash; i++) {
68 AlgorithmEnum& hash = config->getAlgoAt(HashAlgorithm, i);
69 setHashType(i, (int8_t*)hash.getName());
70 }
71
72 lenField |= nCipher << 12;
73 for (int32_t i = 0; i < nCipher; i++) {
74 AlgorithmEnum& cipher = config->getAlgoAt(CipherAlgorithm, i);
75 setCipherType(i, (int8_t*)cipher.getName());
76 }
77
78 lenField |= nAuth << 8;
79 for (int32_t i = 0; i < nAuth; i++) {
80 AlgorithmEnum& length = config->getAlgoAt(AuthLength, i);
81 setAuthLen(i, (int8_t*)length.getName());
82 }
83
84 lenField |= nPubkey << 4;
85 for (int32_t i = 0; i < nPubkey; i++) {
86 AlgorithmEnum& pubKey = config->getAlgoAt(PubKeyAlgorithm, i);
87 setPubKeyType(i, (int8_t*)pubKey.getName());
88 }
89
90 lenField |= nSas;
91 for (int32_t i = 0; i < nSas; i++) {
92 AlgorithmEnum& sas = config->getAlgoAt(SasType, i);
93 setSasType(i, (int8_t*)sas.getName());
94 }
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -050095 *((uint32_t*)&helloHeader->flags) = zrtpHtonl(lenField);
Alexandre Lision51140e12013-12-02 10:54:09 -050096}
97
98ZrtpPacketHello::ZrtpPacketHello(uint8_t *data) {
99 DEBUGOUT((fprintf(stdout, "Creating Hello packet from data\n")));
100
101 zrtpHeader = (zrtpPacketHeader_t *)&((HelloPacket_t *)data)->hdr; // the standard header
102 helloHeader = (Hello_t *)&((HelloPacket_t *)data)->hello;
103
Alexandre Lision907ed2e2014-02-04 10:33:09 -0500104 // Force the isLengthOk() check to fail when we process the packet.
105 if (getLength() < HELLO_FIXED_PART_LEN) {
106 computedLength = 0;
107 return;
108 }
109
Alexandre Lision51140e12013-12-02 10:54:09 -0500110 uint32_t t = *((uint32_t*)&helloHeader->flags);
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500111 uint32_t temp = zrtpNtohl(t);
Alexandre Lision51140e12013-12-02 10:54:09 -0500112
113 nHash = (temp & (0xf << 16)) >> 16;
Alexandre Lision907ed2e2014-02-04 10:33:09 -0500114 nHash &= 0x7; // restrict to max 7 algorithms
Alexandre Lision51140e12013-12-02 10:54:09 -0500115 nCipher = (temp & (0xf << 12)) >> 12;
Alexandre Lision907ed2e2014-02-04 10:33:09 -0500116 nCipher &= 0x7;
Alexandre Lision51140e12013-12-02 10:54:09 -0500117 nAuth = (temp & (0xf << 8)) >> 8;
Alexandre Lision907ed2e2014-02-04 10:33:09 -0500118 nAuth &= 0x7;
Alexandre Lision51140e12013-12-02 10:54:09 -0500119 nPubkey = (temp & (0xf << 4)) >> 4;
Alexandre Lision907ed2e2014-02-04 10:33:09 -0500120 nPubkey &= 0x7;
Alexandre Lision51140e12013-12-02 10:54:09 -0500121 nSas = temp & 0xf;
Alexandre Lision907ed2e2014-02-04 10:33:09 -0500122 nSas &= 0x7;
Alexandre Lision7fd5d3d2013-12-04 13:06:40 -0500123
124 // +2 : the MAC at the end of the packet
125 computedLength = nHash + nCipher + nAuth + nPubkey + nSas + sizeof(HelloPacket_t)/ZRTP_WORD_SIZE + 2;
Alexandre Lision51140e12013-12-02 10:54:09 -0500126
127 oHash = sizeof(Hello_t);
128 oCipher = oHash + (nHash * ZRTP_WORD_SIZE);
129 oAuth = oCipher + (nCipher * ZRTP_WORD_SIZE);
130 oPubkey = oAuth + (nAuth * ZRTP_WORD_SIZE);
131 oSas = oPubkey + (nPubkey * ZRTP_WORD_SIZE);
132 oHmac = oSas + (nSas * ZRTP_WORD_SIZE); // offset to HMAC
133}
134
135ZrtpPacketHello::~ZrtpPacketHello() {
136 DEBUGOUT((fprintf(stdout, "Deleting Hello packet: alloc: %x\n", allocated)));
137}
Alexandre Lision907ed2e2014-02-04 10:33:09 -0500138
139int32_t ZrtpPacketHello::getVersionInt() {
140 uint8_t* vp = getVersion();
141 int32_t version = 0;
142
143 if (isdigit(*vp) && isdigit(*vp+2)) {
144 version = (*vp - '0') * 10;
145 version += *(vp+2) - '0';
146 }
147 return version;
148}