UCommon
secure.h
Go to the documentation of this file.
1// Copyright (C) 2010-2014 David Sugar, Tycho Softworks.
2// Copyright (C) 2015-2020 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:
149 error_t error;
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
878typedef Digest digest_t;
879
883typedef HMAC hmac_t;
884
888typedef Cipher cipher_t;
889
893typedef Cipher::Key skey_t;
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:
914 secure::session_t ssl;
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:
932 sstream(secure::client_t context);
933
941 sstream(const TCPServer *server, secure::server_t context, size_t size = 536);
942
946 ~sstream();
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
Various miscellaneous platform specific headers and defines.
T * init(T *memory)
Template function to initialize memory by invoking default constructor.
Definition platform.h:566
Top level include file for the GNU uCommon C++ core library.
Common namespace for all ucommon objects.
Definition access.h:47
T &() min(T &o1, T &o2)
Convenience function to return min of two objects.
Definition generics.h:461
Cipher cipher_t
Convenience type for generic ciphers.
Definition secure.h:888
T &() max(T &o1, T &o2)
Convenience function to return max of two objects.
Definition generics.h:450
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
class __attribute__((visibility("default"))) sstream void clearmem(T &var)
Secure socket using std::iostream.
Definition secure.h:1017
const struct sockaddr * addr(Socket::address &address)
A convenience function to convert a socket address list into a socket address.
Definition socket.h:2089