1
// ---------------------------------------------------------------------------
3
// - afnix:tls service - tls cipher suite class implementation -
4
// ---------------------------------------------------------------------------
5
// - This program is free software; you can redistribute it and/or modify -
6
// - it provided that this copyright notice is kept intact. -
8
// - This program is distributed in the hope that it will be useful, but -
9
// - without any warranty; without even the implied warranty of -
10
// - merchantability or fitness for a particular purpose. In no event shall -
11
// - the copyright holder be liable for any direct, indirect, incidental or -
12
// - special damages arising in any way out of the use of this software. -
13
// ---------------------------------------------------------------------------
14
// - copyright (c) 1999-2015 amaury darsch -
15
// ---------------------------------------------------------------------------
18
#include "Boolean.hpp"
19
#include "Integer.hpp"
20
#include "Utility.hpp"
21
#include "TlsSuite.hpp"
22
#include "QuarkZone.hpp"
23
#include "Exception.hpp"
27
// -------------------------------------------------------------------------
28
// - private section -
29
// -------------------------------------------------------------------------
31
// the cipher list definition
32
static const TlsSuite::s_cinfo TLS_LIST_CFR[7] {
34
{"TLS_NULL_WITH_NULL_NULL", "2246", "1.0", "", 0x0000U,
35
TlsSuite::TLS_EXCH_NIL,
36
TlsSuite::TLS_CIFR_NIL, TlsSuite::TLS_CPAD_NIL, 0L,
37
TlsSuite::TLS_HASH_NIL, 0L},
39
{"TLS_RSA_WITH_NULL_MD5", "2246", "1.0", "", 0x0001U,
40
TlsSuite::TLS_EXCH_RSA,
41
TlsSuite::TLS_CIFR_NIL, TlsSuite::TLS_CPAD_NIL, 0L,
42
TlsSuite::TLS_HASH_MD5, 0L},
44
{"TLS_RSA_WITH_NULL_SHA", "2246", "1.0", "", 0x0002U,
45
TlsSuite::TLS_EXCH_RSA,
46
TlsSuite::TLS_CIFR_NIL, TlsSuite::TLS_CPAD_NIL, 0L,
47
TlsSuite::TLS_HASH_SHA, 1L},
49
{"TLS_RSA_WITH_RC4_128_MD5", "2246", "1.0", "", 0x0004U,
50
TlsSuite::TLS_EXCH_RSA,
51
TlsSuite::TLS_CIFR_RC4, TlsSuite::TLS_CPAD_NIL, 128L,
52
TlsSuite::TLS_HASH_MD5, 0L},
54
{"TLS_RSA_WITH_RC4_128_SHA", "2246", "1.0", "", 0x0005U,
55
TlsSuite::TLS_EXCH_RSA,
56
TlsSuite::TLS_CIFR_RC4, TlsSuite::TLS_CPAD_NIL, 128L,
57
TlsSuite::TLS_HASH_SHA, 1L},
59
{"TLS_RSA_WITH_AES_128_CBC_SHA", "3268", "1.0", "", 0x002FU,
60
TlsSuite::TLS_EXCH_RSA,
61
TlsSuite::TLS_CIFR_AES, TlsSuite::TLS_CPAD_CBC, 128L,
62
TlsSuite::TLS_HASH_SHA, 1L},
64
{"TLS_RSA_WITH_AES_256_CBC_SHA", "3268", "1.0", "", 0x0035U,
65
TlsSuite::TLS_EXCH_RSA,
66
TlsSuite::TLS_CIFR_AES, TlsSuite::TLS_CPAD_CBC, 256L,
67
TlsSuite::TLS_HASH_SHA, 1L}
69
// the cipher list size
70
static const long TLS_SIZE_CFR =
71
sizeof (TLS_LIST_CFR) / sizeof (TlsSuite::s_cinfo);
73
// find a cipher info structure index by code
74
static inline long tls_find_cinfo (const t_word code) {
75
for (long k = 0L; k < TLS_SIZE_CFR; k++) {
76
if (TLS_LIST_CFR[k].d_code == code) return k;
82
// convert a tls code into a string representation
83
static inline String tls_to_string (const t_word code) {
84
t_byte ucod = (t_byte) (code >> 8);
85
t_byte lcod = (t_byte) (code & 0x00FF);
86
String sval = Utility::tohexa (ucod, true, true) + ", " +
87
Utility::tohexa (lcod, true, true);
91
// fill a property list with a cipher info by index
92
static Plist& tls_add_plist (Plist& plst, const TlsSuite::s_cinfo& cinf) {
94
String name = cinf.d_name;
95
String info = cinf.d_rfcr + ':' + cinf.d_vmin + ':' + cinf.d_vmax;
96
String scod = tls_to_string (cinf.d_code);
97
plst.add (name, info, scod);
101
// get a cipher info print table
102
static PrintTable* tls_get_table (void) {
103
// create a five columns table
104
PrintTable* ptbl = new PrintTable (5);
106
ptbl->sethead (0, "NAME");
107
ptbl->sethead (1, "RFC");
108
ptbl->sethead (2, "MINV");
109
ptbl->sethead (3, "MAXV");
110
ptbl->sethead (4, "CODE");
111
// loop and fill table
112
for (long k = 0L; k < TLS_SIZE_CFR; k++) {
113
long row = ptbl->add ();
114
ptbl->set (row, 0, TLS_LIST_CFR[k].d_name);
115
ptbl->set (row, 1, TLS_LIST_CFR[k].d_rfcr);
116
ptbl->set (row, 2, TLS_LIST_CFR[k].d_vmin);
117
ptbl->set (row, 3, TLS_LIST_CFR[k].d_vmax);
118
ptbl->set (row, 4, tls_to_string (TLS_LIST_CFR[k].d_code));
123
// -------------------------------------------------------------------------
124
// - public section -
125
// -------------------------------------------------------------------------
127
// create a default cipher info structure
129
TlsSuite::s_cinfo::s_cinfo (void) {
130
d_name = "TLS_NULL_WITH_NULL_NULL";
135
d_exch = TLS_EXCH_NIL;
136
d_cifr = TLS_CIFR_NIL;
137
d_cpad = TLS_CPAD_NIL;
139
d_hash = TLS_HASH_NIL;
143
// create a cipher with a brace initializer list
145
TlsSuite::s_cinfo::s_cinfo (const String& name, const String& rfcr,
146
const String& vmin, const String& vmax,
147
const t_word code, const t_exch exch,
148
const t_cifr cifr, const t_cpad cpad,
149
const long csiz, const t_hash hash,
164
// copy construct this cipher info
166
TlsSuite::s_cinfo::s_cinfo (const s_cinfo& that) {
167
d_name = that.d_name;
168
d_rfcr = that.d_rfcr;
169
d_vmin = that.d_vmin;
170
d_vmax = that.d_vmax;
171
d_code = that.d_code;
172
d_exch = that.d_exch;
173
d_cifr = that.d_cifr;
174
d_cpad = that.d_cpad;
175
d_csiz = that.d_csiz;
176
d_hash = that.d_hash;
177
d_hsiz = that.d_hsiz;
180
// assign a cipher info to this one
182
TlsSuite::s_cinfo& TlsSuite::s_cinfo::operator = (const s_cinfo& that) {
183
// check for self-assignation
184
if (this == &that) return *this;
186
d_name = that.d_name;
187
d_rfcr = that.d_rfcr;
188
d_vmin = that.d_vmin;
189
d_vmax = that.d_vmax;
190
d_code = that.d_code;
191
d_exch = that.d_exch;
192
d_cifr = that.d_cifr;
193
d_cpad = that.d_cpad;
194
d_csiz = that.d_csiz;
195
d_hash = that.d_hash;
196
d_hsiz = that.d_hsiz;
200
// convert a cipher code to a word
202
t_word TlsSuite::toword (const t_byte ucod, const t_byte lcod) {
203
t_word result = ucod;
204
result = result << 8; result += lcod;
208
// convert a tls suite code to a upper code
210
t_byte TlsSuite::toucod (const t_word code) {
211
t_byte result = (t_byte) (code >> 8);
215
// convert a tls suite code to a lpper code
217
t_byte TlsSuite::tolcod (const t_word code) {
218
t_byte result = (t_byte) (code & 0x0FU);
222
// -------------------------------------------------------------------------
224
// -------------------------------------------------------------------------
226
// create a default suite
228
TlsSuite::TlsSuite (void) {
234
// create a suite by size
236
TlsSuite::TlsSuite (const long size) {
238
throw Exception ("tls-error", "invalid suite size");
242
p_slst = (d_size == 0L) ? nilp : new t_word[d_size];
246
// destroy this suite
248
TlsSuite::~TlsSuite (void) {
253
// return the class name
255
String TlsSuite::repr (void) const {
261
void TlsSuite::reset (void) {
265
for (long k = 0L; k < d_size; k++) p_slst[k] = nilw;
273
// get the cipher list info as a plist
275
Plist TlsSuite::getinfo (void) const {
278
// create a result plist
281
for (long k = 0L; k < d_slen; k++) {
282
if (isvalid (p_slst[k]) == true) {
283
tls_add_plist (plst, getcinfo (p_slst[k]));
295
// get the number of ciphers in the list
297
long TlsSuite::length (void) const {
300
long result = d_slen;
309
// pop the first valid cipher code
311
t_word TlsSuite::pop (void) const {
314
for (long k = 0L; k < d_slen; k++) {
315
if (isvalid (p_slst[k]) == true) {
316
t_word result = p_slst[k];
326
throw Exception ("tls-error", "cannot find any valid cipher");
329
// get a tls suite code by index
331
t_word TlsSuite::get (const long idx) const {
334
if ((idx < 0L) || (idx >= d_slen)) {
335
throw Exception ("tls-error", "invalid tls suite index");
337
t_word result = p_slst[idx];
346
// add a new cipher in the list by code
348
void TlsSuite::add (const t_word code) {
351
// check size invariant
352
if (d_slen > d_size) {
353
throw Exception ("internal-error", "inconsisten tls suite size");
356
if (d_slen == d_size) {
357
long size = (d_size == 0L) ? 1L : 2L * d_size;
358
t_word* slst = new t_word[size];
359
for (long k = 0; k < d_size; k++) slst[k] = p_slst[k];
360
for (long k = d_size; k < size; k++) slst[k] = nilw;
362
delete [] p_slst; p_slst = slst;
365
p_slst[d_slen++] = code;
373
// add a new cipher in the list by tls code
375
void TlsSuite::add (const t_byte ucod, const t_byte lcod) {
378
// convert into a word code
379
t_word code = TlsSuite::toword (ucod, lcod);
389
// check if a cipher is valid by code
391
bool TlsSuite::isvalid (const t_word code) const {
394
// find a standard structure info index by code
395
long cidx = tls_find_cinfo (code);
397
bool result = (cidx == -1) ? false : true;
406
// check if a cipher is valid by code
408
bool TlsSuite::isvalid (const t_byte ucod, const t_byte lcod) const {
411
// convert into a word code
412
t_word code = TlsSuite::toword (ucod, lcod);
413
// and now test for it
414
bool result = isvalid (code);
423
// find a cipher info structure by code
425
TlsSuite::s_cinfo TlsSuite::getcinfo (const t_word code) const {
428
// find a standard structure info index by code
429
long cidx = tls_find_cinfo (code);
431
throw Exception ("tls-error", "cannot find cipher info with code",
432
Utility::tohexa (code, true, true));
434
TlsSuite::s_cinfo result = TLS_LIST_CFR[cidx];
443
// find a cipher info structure by tls code
445
TlsSuite::s_cinfo TlsSuite::getcinfo (const t_byte ucod,
446
const t_byte lcod) const {
449
// convert into a word code
450
t_word code = TlsSuite::toword (ucod, lcod);
451
// and get the cipher info
452
TlsSuite::s_cinfo result = getcinfo (code);
461
// get cipher suite as a print table
463
PrintTable* TlsSuite::gettinfo (void) const {
466
PrintTable* result = tls_get_table ();
475
// -------------------------------------------------------------------------
476
// - object section -
477
// -------------------------------------------------------------------------
480
static const long QUARK_ZONE_LENGTH = 3;
481
static QuarkZone zone (QUARK_ZONE_LENGTH);
483
// the object supported quarks
484
static const long QUARK_LENGTH = zone.intern ("length");
485
static const long QUARK_VALIDP = zone.intern ("valid-p");
486
static const long QUARK_GETTINFO = zone.intern ("get-info-table");
488
// create a new object in a generic way
490
Object* TlsSuite::mknew (Vector* argv) {
491
// get the number of arguments
492
long argc = (argv == nilp) ? 0 : argv->length ();
494
// check for 0 argument
495
if (argc == 0) return new TlsSuite;
496
// check for 1 argument
498
long size = argv->getlong (0);
499
return new TlsSuite (size);
501
// too many arguments
502
throw Exception ("argument-error",
503
"too many argument with tls cipher suite");
506
// return true if the given quark is defined
508
bool TlsSuite::isquark (const long quark, const bool hflg) const {
510
if (zone.exists (quark) == true) {
514
bool result = hflg ? TlsInfos::isquark (quark, hflg) : false;
519
// apply this object with a set of arguments and a quark
521
Object* TlsSuite::apply (Runnable* robj, Nameset* nset, const long quark,
523
// get the number of arguments
524
long argc = (argv == nilp) ? 0 : argv->length ();
526
// check for 0 argument
528
if (quark == QUARK_LENGTH) return new Integer (length ());
529
if (quark == QUARK_GETTINFO) return gettinfo ();
531
// check for 1 argument
533
if (quark == QUARK_VALIDP) {
534
t_word code = argv->getword (0);
535
return new Boolean (isvalid (code));
538
// call the tls infos method
539
return TlsInfos::apply (robj, nset, quark, argv);