UCommon
secure.h
Go to the documentation of this file.
1// Copyright (C) 2010-2014 David Sugar, Tycho Softworks.
2// Copyright (C) 2015 Cherokees of Idaho.
3//
4// This file is part of GNU uCommon C++.
5//
6// GNU uCommon C++ is free software: you can redistribute it and/or modify
7// it under the terms of the GNU Lesser General Public License as published
8// by the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// GNU uCommon C++ is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU Lesser General Public License for more details.
15//
16// You should have received a copy of the GNU Lesser General Public License
17// along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
18
42#ifndef _UCOMMON_SECURE_H_
43#define _UCOMMON_SECURE_H_
44
45#ifndef _UCOMMON_CONFIG_H_
46#include <ucommon/platform.h>
47#endif
48
49#ifndef _UCOMMON_UCOMMON_H_
50#include <ucommon/ucommon.h>
51#endif
52
53#define MAX_CIPHER_KEYSIZE 512
54#define MAX_DIGEST_HASHSIZE 512
55
56namespace ucommon {
57
58class __SHARED AutoClear
59{
60private:
61 __DELETE_DEFAULTS(AutoClear);
62
63protected:
64 size_t size;
65 void *pointer;
66
67 AutoClear(size_t alloc);
68
69public:
70 virtual ~AutoClear();
71};
72
73template<typename T>
74class autoclear : public AutoClear
75{
76private:
77 __DELETE_COPY(autoclear);
78
79public:
80 autoclear() : AutoClear(sizeof(T)) {};
81
82 inline operator T() {
83 return *(static_cast<T*>(pointer));
84 }
85
86 inline T& operator*() {
87 return *(static_cast<T*>(pointer));
88 }
89
90 inline T* operator->() {
91 return static_cast<T*>(pointer);
92 }
93};
94
95template <>
96class autoclear<char *> : public AutoClear
97{
98private:
99 __DELETE_COPY(autoclear);
100
101public:
102 autoclear(size_t len) : AutoClear(len) {};
103
104 inline char *operator*() {
105 return (char *)pointer;
106 }
107};
108
109template <>
110class autoclear<uint8_t *> : public AutoClear
111{
112private:
113 __DELETE_COPY(autoclear);
114
115public:
116 autoclear(size_t len) : AutoClear(len) {};
117
118 inline char *operator*() {
119 return (char *)pointer;
120 }
121};
122
128class __SHARED secure
129{
130public:
134 typedef enum {OK=0, INVALID, MISSING_CERTIFICATE, MISSING_PRIVATEKEY, INVALID_CERTIFICATE, INVALID_AUTHORITY, INVALID_PEERNAME, INVALID_CIPHER} error_t;
135
136 typedef enum {NONE, SIGNED, VERIFIED} verify_t;
137
138 typedef stringref<secure_release> string;
139
140 typedef byteref<secure_release> keybytes;
141
142private:
143 __DELETE_COPY(secure);
144
145protected:
150
151 inline secure() {error = OK;}
152
153public:
158 virtual ~secure();
159
163 typedef secure *client_t;
164
165 typedef secure *server_t;
166
170 typedef void *session_t;
171
175 typedef void *cert_t;
176
180 typedef void *bufio_t;
181
187 static bool init(void);
188
195 static bool fips(void);
196
202 static int oscerts(const char *path);
203
208 static const char *oscerts(void);
209
219 static server_t server(const char *keyfile = NULL, const char *authority = NULL);
220
228 static client_t client(const char *authority = NULL, const char *paths = NULL);
229
236 static client_t user(const char *authority);
237
243 static void cipher(secure *context, const char *ciphers);
244
249 inline bool is_valid(void) const {
250 return error == OK;
251 };
252
257 inline error_t err(void) const {
258 return error;
259 };
260
265 static void uuid(char *string);
266
267 static secure::string pass(const char *prompt, size_t size);
268
269 static secure::string uuid(void);
270
271 inline operator bool() const {
272 return is_valid();
273 }
274
275 inline bool operator!() const {
276 return !is_valid();
277 }
278};
279
289class __SHARED Cipher
290{
291public:
292 typedef enum {ENCRYPT = 1, DECRYPT = 0} mode_t;
293
301 class __SHARED Key
302 {
303 protected:
304 friend class Cipher;
305
306 union {
307 const void *algotype;
308 int algoid;
309 };
310
311 union {
312 const void *hashtype;
313 int hashid;
314 };
315
316 int modeid;
317
318 // assume 512 bit cipher keys possible...
319 uint8_t keybuf[MAX_CIPHER_KEYSIZE / 8], ivbuf[MAX_CIPHER_KEYSIZE / 8];
320
321 // generated keysize
322 size_t keysize, blksize;
323
324 Key(const char *ciper);
325
326 void set(const char *cipher);
327
328 public:
329 Key();
330
331 Key(const char *cipher, const char *digest, const char *text, size_t size = 0, const uint8_t *salt = NULL, unsigned rounds = 1);
332
333 Key(const char *cipher, const uint8_t *iv, size_t ivsize);
334
335 Key(const char *cipher, secure::keybytes& iv);
336
337 Key(const char *cipher, const char *digest);
338
339 ~Key();
340
341 void set(const uint8_t *key, size_t size);
342
343 inline secure::keybytes key() {
344 return secure::keybytes(keybuf, keysize);
345 }
346
347 inline secure::keybytes iv() {
348 return secure::keybytes(ivbuf, blksize);
349 }
350
351 bool set(const secure::keybytes& key);
352
353 void set(const char *cipher, const char *digest);
354
355 void set(const char *cipher, const uint8_t *iv, size_t ivsize);
356
357 void assign(const char *key, size_t size, const uint8_t *salt, unsigned rounds);
358
359 bool set(const char *cipher, const secure::keybytes& iv);
360
361 void assign(const char *key, size_t size = 0);
362
363 void clear(void);
364
365 secure::string b64(void);
366
367 void b64(const char *string);
368
369 size_t get(uint8_t *key, uint8_t *ivout = NULL);
370
371 inline size_t size(void) const {
372 return keysize;
373 }
374
375 inline size_t iosize(void) const {
376 return blksize;
377 }
378
379 inline operator bool() const {
380 return keysize > 0;
381 }
382
383 inline bool operator!() const {
384 return keysize == 0;
385 }
386
387 inline Key& operator=(const char *pass) {
388 assign(pass);
389 return *this;
390 }
391
392 bool operator==(const Key& other) const;
393
394 inline bool operator!=(const Key& other) const {
395 return !operator==(other);
396 }
397
398 static void options(const uint8_t *salt = NULL, unsigned rounds = 1);
399 };
400
401 typedef Key *key_t;
402
403private:
404 Key keys;
405 size_t bufsize, bufpos;
406 mode_t bufmode;
407 uint8_t *bufaddr;
408 void *context;
409
410 __DELETE_COPY(Cipher);
411
412protected:
413 virtual void push(uint8_t *address, size_t size);
414
415 void release(void);
416
417public:
418 Cipher();
419
420 Cipher(const key_t key, mode_t mode, uint8_t *address = NULL, size_t size = 0);
421
422 virtual ~Cipher();
423
424 void set(uint8_t *address, size_t size = 0);
425
426 void set(const key_t key, mode_t mode, uint8_t *address, size_t size = 0);
427
428 inline secure::keybytes iv() {
429 return keys.iv();
430 }
431
432 inline secure::keybytes key() {
433 return keys.key();
434 }
435
440 size_t flush(void);
441
450 size_t put(const uint8_t *data, size_t size);
451
458 size_t puts(const char *string);
459
471 size_t pad(const uint8_t *address, size_t size);
472
481 size_t process(uint8_t *address, size_t size, bool flag = false);
482
483 inline size_t size(void) const {
484 return bufsize;
485 }
486
487 inline size_t pos(void) const {
488 return bufpos;
489 }
490
491 inline size_t align(void) const {
492 return keys.iosize();
493 }
494
500 static bool has(const char *name);
501};
502
509class __SHARED Digest
510{
511private:
512 void *context;
513
514 union {
515 const void *hashtype;
516 int hashid;
517 };
518
519 unsigned bufsize;
520 uint8_t buffer[MAX_DIGEST_HASHSIZE / 8];
521 char textbuf[MAX_DIGEST_HASHSIZE / 8 + 1];
522
523 __DELETE_COPY(Digest);
524
525protected:
526 void release(void);
527
528 const uint8_t *get(void);
529
530public:
531 Digest(const char *type);
532
533 Digest();
534
535 ~Digest();
536
537 inline bool puts(const char *str) {
538 return put(str, strlen(str));
539 }
540
541 inline Digest &operator<<(const char *str) {
542 puts(str);
543 return *this;
544 }
545
546 inline Digest &operator<<(int16_t value) {
547 int16_t v = htons(value);
548 put(&v, 2);
549 return *this;
550 }
551
552 inline Digest &operator<<(int32_t value) {
553 int32_t v = htonl(value);
554 put(&v, 4);
555 return *this;
556 }
557
558 inline Digest &operator<<(const PrintProtocol& p) {
559 const char *cp = p._print();
560 if(cp)
561 puts(cp);
562 return *this;
563 }
564
565 bool put(const void *memory, size_t size);
566
567 inline unsigned size() const {
568 return bufsize;
569 }
570
571 secure::keybytes key(void);
572
573 secure::string str(void);
574
575 inline operator secure::string() {
576 return str();
577 }
578
579 void set(const char *id);
580
581 inline Digest& operator=(const char *id) {
582 set(id);
583 return *this;
584 };
585
586 inline bool operator *=(const char *text) {
587 return puts(text);
588 }
589
590 inline bool operator +=(const char *text) {
591 return puts(text);
592 }
593
594 inline secure::string operator*() {
595 return str();
596 }
597
598 inline bool operator!() const {
599 return !bufsize && context == NULL;
600 }
601
602 inline operator bool() const {
603 return bufsize > 0 || context != NULL;
604 }
605
611 void recycle(bool binary = false);
612
616 void reset(void);
617
623 static bool has(const char *name);
624
625 static secure::string uuid(const char *name, const uint8_t *ns = NULL);
626
632 static secure::string md5(const char *text);
633
634 static secure::string sha1(const char *text);
635
636 static secure::string sha256(const char *text);
637
638 static secure::string sha384(const char *text);
639
640 static secure::keybytes md5(const uint8_t *mem, size_t size);
641
642 static secure::keybytes sha1(const uint8_t *mem, size_t size);
643
644 static secure::keybytes sha256(const uint8_t *mem, size_t size);
645
646 static secure::keybytes sha384(const uint8_t *mem, size_t size);
647
648};
649
656class __SHARED HMAC
657{
658private:
659 void *context;
660
661 union {
662 const void *hmactype;
663 int hmacid;
664 };
665
666 unsigned bufsize;
667 uint8_t buffer[MAX_DIGEST_HASHSIZE / 8];
668 char textbuf[MAX_DIGEST_HASHSIZE / 8 + 1];
669
670 __DELETE_COPY(HMAC);
671
672protected:
673 void release(void);
674
675 const uint8_t *get(void);
676
677public:
678 HMAC(const char *digest, const secure::keybytes& key);
679
680 HMAC();
681
682 ~HMAC();
683
684 inline bool puts(const char *str) {
685 return put(str, strlen(str));
686 }
687
688 inline HMAC &operator<<(const char *str) {
689 puts(str);
690 return *this;
691 }
692
693 inline HMAC &operator<<(int16_t value) {
694 int16_t v = htons(value);
695 put(&v, 2);
696 return *this;
697 }
698
699 inline HMAC &operator<<(int32_t value) {
700 int32_t v = htonl(value);
701 put(&v, 4);
702 return *this;
703 }
704
705 inline HMAC &operator<<(const PrintProtocol& p) {
706 const char *cp = p._print();
707 if(cp)
708 puts(cp);
709 return *this;
710 }
711
712 bool put(const void *memory, size_t size);
713
714 inline unsigned size() const {
715 return bufsize;
716 }
717
718 secure::string str(void);
719
720 secure::keybytes key(void);
721
722 inline operator secure::string() {
723 return str();
724 }
725
726 inline bool operator *=(const char *text) {
727 return puts(text);
728 }
729
730 void set(const char *digest, const secure::keybytes& key);
731
732 inline bool operator +=(const char *text) {
733 return puts(text);
734 }
735
736 inline secure::string operator*() {
737 return str();
738 }
739
740 inline bool operator!() const {
741 return !bufsize && context == NULL;
742 }
743
744 inline operator bool() const {
745 return bufsize > 0 || context != NULL;
746 }
747
753 static bool has(const char *name);
754
755 static secure::keybytes sha256(secure::keybytes key, const uint8_t *mem, size_t size);
756
757 static secure::keybytes sha384(secure::keybytes key, const uint8_t *mem, size_t soze);
758};
759
765class __SHARED Random
766{
767private:
768 __DELETE_DEFAULTS(Random);
769
770public:
777 static bool seed(const uint8_t *buffer, size_t size);
778
782 static void seed(void);
783
792 static size_t key(uint8_t *memory, size_t size);
793
802 static size_t fill(uint8_t *memory, size_t size);
803
808 static int get(void);
809
816 static int get(int min, int max);
817
822 static double real(void);
823
830 static double real(double min, double max);
831
837 static bool status(void);
838
843 static void uuid(char *string);
844
845 static secure::string uuid(void);
846
847 template <class T>
848 inline static T value(void) {
849 T tmp;
850 Random::key(reinterpret_cast<uint8_t *>(&tmp), sizeof(tmp));
851 return tmp;
852 }
853
854 template <class T>
855 inline static T value(T max) {
856 T slice;
857 T value;
858
859 value = 0xffffffff;
860 slice = 0xffffffff / max;
861 while(value >= max) {
862 value = Random::value<T>() / slice;
863 }
864 return value;
865 }
866
867 template <class T>
868 inline static T value(T min, T max)
869 {
870 return min + Random::value<T>(max - min);
871 }
872};
873
874
879
883typedef HMAC hmac_t;
884
889
894
895inline void zerofill(void *addr, size_t size)
896{
897 ::memset(addr, 0, size);
898}
899
900#ifndef UCOMMON_SYSRUNTIME
901
908class __SHARED sstream : public tcpstream
909{
910private:
911 __DELETE_COPY(sstream);
912
913protected:
915 secure::bufio_t bio;
916 secure::cert_t cert;
917 secure::verify_t verified;
918 bool server;
919
920 ssize_t _write(const char *address, size_t size) __OVERRIDE;
921
922 ssize_t _read(char *address, size_t size) __OVERRIDE;
923
924 bool _wait(void) __OVERRIDE;
925
926public:
933
941 sstream(const TCPServer *server, secure::server_t context, size_t size = 536);
942
947
954 void open(const char *host, const char *service, size_t size = 536);
955
959 void close(void);
960
964 void release(void);
965
966 int sync() __OVERRIDE;
967
968 inline void flush(void) {
969 sync();
970 }
971
976 inline secure::cert_t certificate(void) const {
977 return cert;
978 }
979
984 inline bool is_secure(void) const {
985 return bio != NULL;
986 }
987
992 inline bool is_certificate(void) const {
993 return cert != NULL;
994 }
995
1000 inline bool is_verified(void) const {
1001 return verified == secure::VERIFIED;
1002 }
1003
1008 inline bool is_signed(void) const {
1009 return verified != secure::NONE;
1010 }
1011};
1012
1013#endif
1014
1015// can be specialized...
1016template<typename T>
1017void clearmem(T &var)
1018{
1019 memset(&var, 0, sizeof(var));
1020}
1021
1022typedef secure::string keystring_t;
1023
1024} // namespace ucommon
1025
1026#endif
Top level include file for the GNU uCommon C++ core library.
Various miscellaneous platform specific headers and defines.
Common namespace for all ucommon objects.
Definition access.h:47
T & max(T &o1, T &o2)
Convenience function to return max of two objects.
Definition generics.h:445
Cipher cipher_t
Convenience type for generic ciphers.
Definition secure.h:888
Digest digest_t
Convenience type for generic digests.
Definition secure.h:878
HMAC hmac_t
Convenience type for generic digests.
Definition secure.h:883
Cipher::Key skey_t
Convenience type for generic cipher key.
Definition secure.h:893
const struct sockaddr * addr(Socket::address &address)
A convenience function to convert a socket address list into a socket address.
Definition socket.h:2089
T & min(T &o1, T &o2)
Convenience function to return min of two objects.
Definition generics.h:456
Traditional keypair config file parsing class.
Definition keydata.h:161
Used for forming stream output.
Definition protocols.h:135
virtual const char * _print(void) const =0
Extract formatted string for object.
Common secure socket support.
Definition secure.h:129
error_t error
Last error flagged for this context.
Definition secure.h:149
void * session_t
Convenience type to represent a secure socket session.
Definition secure.h:170
static const char * oscerts(void)
Get path to system certificates.
bool is_valid(void) const
Determine if the current security context is valid.
Definition secure.h:249
static server_t server(const char *keyfile=NULL, const char *authority=NULL)
Create a sever context.
static int oscerts(const char *path)
Copy system certificates to a local path.
static client_t client(const char *authority=NULL, const char *paths=NULL)
Create an anonymous client context with an optional authority to validate.
static client_t user(const char *authority)
Create a peer user client context.
static bool init(void)
Initialize secure stack for first use, and report if SSL support is compiled in.
static bool fips(void)
Initialize secure stack with fips support.
static void uuid(char *string)
Create 36 character traditional version 1 uuid.
static void cipher(secure *context, const char *ciphers)
Assign a non-default cipher to the context.
error_t
Different error states of the security context.
Definition secure.h:134
void * bufio_t
Convenience type to represent a secure socket buf i/o stream.
Definition secure.h:180
void * cert_t
Convenience type to represent a ssl certificate object.
Definition secure.h:175
secure * client_t
Convenience type to represent a security context.
Definition secure.h:163
virtual ~secure()
This is derived in different back-end libraries, and will be used to clear certificate credentials.
error_t err(void) const
Get last error code associated with the security context.
Definition secure.h:257
A generic data ciphering class.
Definition secure.h:290
size_t process(uint8_t *address, size_t size, bool flag=false)
Process encrypted data in-place.
static bool has(const char *name)
Check if a specific cipher is supported.
size_t puts(const char *string)
This essentially encrypts a single string and pads with NULL bytes as needed.
size_t flush(void)
Push a final cipher block.
size_t pad(const uint8_t *address, size_t size)
This is used to process any data unaligned to the blocksize at the end of a cipher session.
size_t put(const uint8_t *data, size_t size)
Process cipher data.
Cipher key formed by hash algorithm.
Definition secure.h:302
A cryptographic digest class.
Definition secure.h:510
static secure::string md5(const char *text)
Shortcut for short md5 digests if supported...
void reset(void)
Reset and restart digest object.
void recycle(bool binary=false)
Finalize and recycle current digest to start a new digest.
static bool has(const char *name)
Test to see if a specific digest type is supported.
A cryptographic message authentication code class.
Definition secure.h:657
static bool has(const char *name)
Test to see if a specific digest type is supported.
Cryptographically relevant random numbers.
Definition secure.h:766
static void seed(void)
Re-seed pseudo-random generation and entropy pools.
static double real(void)
Get a pseudo-random floating point value.
static double real(double min, double max)
Get a pseudo-random floating point value in a preset range.
static size_t key(uint8_t *memory, size_t size)
Get high-entropy random data.
static int get(int min, int max)
Get a pseudo-random integer in a preset range.
static bool seed(const uint8_t *buffer, size_t size)
Push entropic seed.
static void uuid(char *string)
Create 36 character random uuid string.
static int get(void)
Get a pseudo-random integer, range 0 - 32767.
static bool status(void)
Determine if we have sufficient entropy to return random values.
static size_t fill(uint8_t *memory, size_t size)
Fill memory with pseudo-random values.
Secure socket using std::iostream.
Definition secure.h:909
bool is_certificate(void) const
Check if a peer certificate is present.
Definition secure.h:992
void release(void)
Release all ssl resources.
void open(const char *host, const char *service, size_t size=536)
Open a connection to a ssl server.
sstream(const TCPServer *server, secure::server_t context, size_t size=536)
Construct a ssl server stream.
void close(void)
Close a connection with a ssl server.
secure::cert_t certificate(void) const
Get peer (x509) certificate for current stream if present.
Definition secure.h:976
bool is_secure(void) const
Check if ssl session active, otherwise pure tcp.
Definition secure.h:984
bool is_signed(void) const
Check if peer certificate is present and at least self-signed.
Definition secure.h:1008
~sstream()
Destroy ssl stream.
sstream(secure::client_t context)
Construct a ssl client stream.
bool is_verified(void) const
Check if peer certificate is verified through an authority.
Definition secure.h:1000
A generic tcp server class.
Definition socket.h:1901
Streamable tcp connection between client and server.
Definition stream.h:115