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 
56 namespace ucommon {
57 
58 class __SHARED AutoClear
59 {
60 private:
61  __DELETE_DEFAULTS(AutoClear);
62 
63 protected:
64  size_t size;
65  void *pointer;
66 
67  AutoClear(size_t alloc);
68 
69 public:
70  virtual ~AutoClear();
71 };
72 
73 template<typename T>
74 class autoclear : public AutoClear
75 {
76 private:
77  __DELETE_COPY(autoclear);
78 
79 public:
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 
95 template <>
96 class autoclear<char *> : public AutoClear
97 {
98 private:
99  __DELETE_COPY(autoclear);
100 
101 public:
102  autoclear(size_t len) : AutoClear(len) {};
103 
104  inline char *operator*() {
105  return (char *)pointer;
106  }
107 };
108 
109 template <>
110 class autoclear<uint8_t *> : public AutoClear
111 {
112 private:
113  __DELETE_COPY(autoclear);
114 
115 public:
116  autoclear(size_t len) : AutoClear(len) {};
117 
118  inline char *operator*() {
119  return (char *)pointer;
120  }
121 };
122 
128 class __SHARED secure
129 {
130 public:
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 
142 private:
143  __DELETE_COPY(secure);
144 
145 protected:
150 
151  inline secure() {error = OK;}
152 
153 public:
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 
289 class __SHARED Cipher
290 {
291 public:
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 
403 private:
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 
412 protected:
413  virtual void push(uint8_t *address, size_t size);
414 
415  void release(void);
416 
417 public:
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 
509 class __SHARED Digest
510 {
511 private:
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 
525 protected:
526  void release(void);
527 
528  const uint8_t *get(void);
529 
530 public:
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 
656 class __SHARED HMAC
657 {
658 private:
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 
672 protected:
673  void release(void);
674 
675  const uint8_t *get(void);
676 
677 public:
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 
765 class __SHARED Random
766 {
767 private:
768  __DELETE_DEFAULTS(Random);
769 
770 public:
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 
878 typedef Digest digest_t;
879 
883 typedef HMAC hmac_t;
884 
888 typedef Cipher cipher_t;
889 
894 
895 inline void zerofill(void *addr, size_t size)
896 {
897  ::memset(addr, 0, size);
898 }
899 
900 #ifndef UCOMMON_SYSRUNTIME
901 
908 class __SHARED sstream : public tcpstream
909 {
910 private:
911  __DELETE_COPY(sstream);
912 
913 protected:
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 
926 public:
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...
1016 template<typename T>
1017 void clearmem(T &var)
1018 {
1019  memset(&var, 0, sizeof(var));
1020 }
1021 
1022 typedef secure::string keystring_t;
1023 
1024 } // namespace ucommon
1025 
1026 #endif
Various miscellaneous platform specific headers and defines.
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:456
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
T &() max(T &o1, T &o2)
Convenience function to return max of two objects.
Definition: generics.h:445
const struct sockaddr * addr(Socket::address &address)
A convenience function to convert a socket address list into a socket address.
Definition: socket.h:2089
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
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 const char * oscerts(void)
Get path to system certificates.
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