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:
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...
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
Cipher cipher_t
Convenience type for generic ciphers.
Definition: secure.h:888
Traditional keypair config file parsing class.
Definition: keydata.h:160
T &() max(T &o1, T &o2)
Convenience function to return max of two objects.
Definition: generics.h:445
Secure socket using std::iostream.
Definition: secure.h:908
A generic tcp server class.
Definition: socket.h:1900
Digest digest_t
Convenience type for generic digests.
Definition: secure.h:878
A generic data ciphering class.
Definition: secure.h:289
static size_t key(uint8_t *memory, size_t size)
Get high-entropy random data.
Top level include file for the GNU uCommon C++ core library.
T * init(T *memory)
Template function to initialize memory by invoking default constructor.
Definition: platform.h:551
void * bufio_t
Convenience type to represent a secure socket buf i/o stream.
Definition: secure.h:180
Common secure socket support.
Definition: secure.h:128
secure::cert_t certificate(void) const
Get peer (x509) certificate for current stream if present.
Definition: secure.h:976
virtual const char * _print(void) const =0
Extract formatted string for object.
bool is_verified(void) const
Check if peer certificate is verified through an authority.
Definition: secure.h:1000
Cipher::Key skey_t
Convenience type for generic cipher key.
Definition: secure.h:893
bool is_secure(void) const
Check if ssl session active, otherwise pure tcp.
Definition: secure.h:984
A cryptographic digest class.
Definition: secure.h:509
bool is_valid(void) const
Determine if the current security context is valid.
Definition: secure.h:249
bool is_certificate(void) const
Check if a peer certificate is present.
Definition: secure.h:992
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
error_t
Different error states of the security context.
Definition: secure.h:134
error_t error
Last error flagged for this context.
Definition: secure.h:149
Cryptographically relevant random numbers.
Definition: secure.h:765
Various miscellaneous platform specific headers and defines.
Common namespace for all ucommon objects.
Definition: access.h:47
secure * client_t
Convenience type to represent a security context.
Definition: secure.h:163
HMAC hmac_t
Convenience type for generic digests.
Definition: secure.h:883
void * cert_t
Convenience type to represent a ssl certificate object.
Definition: secure.h:175
bool is_signed(void) const
Check if peer certificate is present and at least self-signed.
Definition: secure.h:1008
Streamable tcp connection between client and server.
Definition: stream.h:114
error_t err(void) const
Get last error code associated with the security context.
Definition: secure.h:257
Cipher key formed by hash algorithm.
Definition: secure.h:301
void * session_t
Convenience type to represent a secure socket session.
Definition: secure.h:170
A cryptographic message authentication code class.
Definition: secure.h:656
Used for forming stream output.
Definition: protocols.h:134