/usr/include/x86_64-linux-gnu/qcc/Crypto.h is in liballjoyn-common-dev-1604 16.04a+dfsg.1-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 | #ifndef _CRYPTO_H
#define _CRYPTO_H
/**
* @file
*
* This file provide wrappers around cryptographic algorithms.
*/
/******************************************************************************
* Copyright AllSeen Alliance. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************************/
#include <qcc/platform.h>
#include <string.h>
#include <stdarg.h>
#include <qcc/KeyBlob.h>
#include <qcc/SecureAllocator.h>
#include <qcc/Stream.h>
#include <qcc/String.h>
namespace qcc {
/**
* AES block encryption/decryption class
*/
class Crypto_AES {
public:
/**
* Size of an AES128 key in bytes
*/
static const size_t AES128_SIZE = (128 / 8);
/**
* AES modes
*/
typedef enum {
ECB_ENCRYPT, ///< Flag to constructor indicating key is being used for ECB encryption
CCM ///< Flag to constructor indicating key is being used CCM mode
} Mode;
/**
* CryptoAES constructor.
*
* @param key The AES key
* @param mode Specifies the operation mode.
*/
Crypto_AES(const KeyBlob& key, Mode mode);
/**
* Data is encrypted or decrypted in 16 byte blocks.
*
* Note we depend on sizeof(Block) == 16
*/
class Block {
public:
uint8_t data[16];
/**
* Constructor that initializes the block.
*
* @param ival The initial value.
*/
Block(uint8_t ival) { memset(data, ival, sizeof(data)); }
/**
* Default constructor.
*/
Block() { };
/**
* Null pad end of block
*/
void Pad(size_t padLen) {
QCC_ASSERT(padLen <= 16);
if (padLen > 0) { memset(&data[16 - padLen], 0, padLen); }
}
};
/**
* Helper function to return the number of blocks required to hold a encrypt a number of bytes.
*
* @param len The data length
* @return The number of blocks for data of the requested length.
*/
static size_t NumBlocks(size_t len) { return (len + sizeof(Block) - 1) / sizeof(Block); }
/**
* Encrypt some data blocks.
*
* @param in An array of data blocks to encrypt
* @param out The encrypted data blocks
* @param numBlocks The number of blocks to encrypt.
*
* @return ER_OK if the data was encrypted.
*/
QStatus Encrypt(const Block* in, Block* out, uint32_t numBlocks);
/**
* Encrypt some data. The encrypted data is padded as needed to round up to a whole number of blocks.
*
* @param in An array of data blocks to encrypt
* @param len The length of the input data
* @param out The encrypted data blocks
* @param numBlocks The number of blocks for the encrypted data, compute this using NumEncryptedBlocks(len)
* @return ER_OK if the data was encrypted.
*/
QStatus Encrypt(const void* in, size_t len, Block* out, uint32_t numBlocks);
/**
* Encrypt some data using CCM mode.
*
* @param in Pointer to the data to encrypt
* @param out The encrypted data, this can be the same as in. The size of this buffer
* must be large enough to hold the encrypted input data and the
* authentication field. This means at least (len + authLen) bytes.
* @param len On input the length of the input data,returns the length of the output data.
* @param nonce A nonce with length between 4 and 14 bytes. The nonce must contain a variable
* component that is different for every encryption in a given session.
* @param addData Additional data to be authenticated.
* @param addLen Length of the additional data.
* @param authLen Lengh of the authentication field, must be in range 4..16
*
* @return ER_OK if the data was encrypted.
*/
QStatus Encrypt_CCM(const void* in, void* out, size_t& len, const KeyBlob& nonce, const void* addData, size_t addLen, uint8_t authLen = 8);
/**
* Convenience wrapper for encrypting and authenticating a header and message in-place.
*
* @param msg Pointer to the entire message. The message buffer must be long enough to
* allow for the authentication field (of length authLen) to be appended.
* @param msgLen On input, the length in bytes of the plaintext message, on output the expanded
* length of the encrypted message.
* @param hdrLen Length in bytes of the header portion of the message
* @param nonce A nonce with length between 4 and 14 bytes. The nonce must contain a variable
* component that is different for every encryption in a given session.
* @param authLen Lengh of the authentication field, must be in range 4..16
*/
QStatus Encrypt_CCM(void* msg, size_t& msgLen, size_t hdrLen, const KeyBlob& nonce, uint8_t authLen = 8)
{
if (!msg) {
return ER_BAD_ARG_1;
}
if (msgLen < hdrLen) {
return ER_BAD_ARG_2;
}
size_t len = msgLen - hdrLen;
QStatus status = Encrypt_CCM((uint8_t*)msg + hdrLen, (uint8_t*)msg + hdrLen, len, nonce, msg, hdrLen, authLen);
msgLen = hdrLen + len;
return status;
}
/**
* Decrypt some data using CCM mode.
*
* @param in An array of to encrypt
* @param out The encrypted data blocks, this can be the same as in.
* @param len On input the length of the input data, returns the length of the output data.
* @param nonce A nonce with length between 11 and 14 bytes. The nonce must contain a variable
* component that is different for every encryption in a given session.
* @param addData Additional data to be authenticated.
* @param addLen Length of the additional data.
* @param authLen Length of the authentication field, must be in range 4..16
*
* @return ER_OK if the data was decrypted and verified.
* ER_AUTH_FAIL if the decryption failed.
*/
QStatus Decrypt_CCM(const void* in, void* out, size_t& len, const KeyBlob& nonce, const void* addData, size_t addLen, uint8_t authLen = 8);
/**
* Convenience wrapper for decrypting and authenticating a header and message in-place.
*
* @param msg Pointer to the entire message.
* @param msgLen On input, the length in bytes of the encrypted message, on output the
* length of the plaintext message.
* @param hdrLen Length in bytes of the header portion of the message
* @param nonce A nonce with length between 11 and 14 bytes. The nonce must contain a variable
* component that is different for every encryption in a given session.
* @param authLen Lengh of the authentication field, must be in range 4..16
*/
QStatus Decrypt_CCM(void* msg, size_t& msgLen, size_t hdrLen, const KeyBlob& nonce, uint8_t authLen = 8)
{
if (!msg) {
return ER_BAD_ARG_1;
}
if (msgLen < hdrLen) {
return ER_BAD_ARG_2;
}
size_t len = msgLen - hdrLen;
QStatus status = Decrypt_CCM((uint8_t*)msg + hdrLen, (uint8_t*)msg + hdrLen, len, nonce, msg, hdrLen, authLen);
msgLen = hdrLen + len;
return status;
}
/**
* Destructor
*/
~Crypto_AES();
private:
Crypto_AES() { }
/**
* Copy constructor is private
*/
Crypto_AES(const Crypto_AES& other);
/**
* Assigment operator is private
*/
Crypto_AES& operator=(const Crypto_AES& other);
/**
* Flag indicating the mode for the class instance.
*/
Mode mode;
/**
* Opaque type for the internal state
*/
struct KeyState;
/**
* Private internal key state
*/
KeyState* keyState;
};
/**
* Generic hash calculation interface abstraction class.
*/
class Crypto_Hash {
public:
/// Typedef for abstracting the hash algorithm specifier.
typedef enum {
SHA1, ///< SHA1 algorithm specifier
SHA256 ///< SHA256 algorithm specifier
} Algorithm;
/**
* Default constructor
*/
Crypto_Hash() : MAC(false), initialized(false), ctx(NULL) { }
/**
* The destructor cleans up the context.
*/
virtual ~Crypto_Hash();
/**
* Virtual initializer to be implemented by derivative classes. The
* derivative classes should call the protected Crypto_Hash::Init()
* function with the appropriate algorithm.
*
* @param hmacKey [optional] An array containing the HMAC key.
* (Defaults to NULL for no key.)
* @param keyLen [optional] The size of the HMAC key.
* (Defaults to 0 for no key.)
*
* @return Indication of success or failure.
*/
virtual QStatus Init(const uint8_t* hmacKey = NULL, size_t keyLen = 0) = 0;
/**
* Update the digest with the contents of the specified buffer.
*
* @param buf Buffer with data for feeding to the hash algorithm.
* @param bufSize Size of the buffer.
*
* @return Indication of success or failure.
*/
QStatus Update(const uint8_t* buf, size_t bufSize);
/**
* Update the digest with the contents of a string
*
* @param str The string to hash.
*
* @return Indication of success or failure.
*/
QStatus Update(const qcc::String& str);
/**
* Update the digest with the contents of a string
*
* @param d The vector<uint8_t> to hash.
*
* @return Indication of success or failure.
*/
QStatus Update(const std::vector<uint8_t, SecureAllocator<uint8_t> >& d);
/**
* Retrieve the digest into the supplied buffer. It is assumed that buffer is large enough to
* store the digest. Unless keepAlive is true, after the digest has been computed the hash
* instance is not longer usable until re-initialized. Keep alive is not allowed for HMAC.
*
* @param digest Buffer for storing the digest.
* @param keepAlive If true, keep the hash computation alive so additional data can be added
* and the updated digest can be computed.
*
* @return Indication of success or failure.
*/
QStatus GetDigest(uint8_t* digest, bool keepAlive = false);
protected:
static const size_t SHA1_SIZE = 20; ///< SHA1 digest size - 20 bytes == 160 bits
static const size_t SHA256_SIZE = 32; ///< SHA256 digest size - 32 bytes == 256 bits
/**
* The common initializer. Derivative classes should call this from their
* public implementation of Init().
*
* @param alg Algorithm to be used for the hash function.
* @param hmacKey An array containing the HMAC key.
* @param keyLen The size of the HMAC key.
*
* @return Indication of success or failure.
*/
QStatus Init(Algorithm alg, const uint8_t* hmacKey = NULL, size_t keyLen = 0);
private:
/**
* No copy constructor
*/
Crypto_Hash(const Crypto_Hash& other);
/**
* No assigment operator
*/
Crypto_Hash& operator=(const Crypto_Hash& other);
bool MAC; ///< Flag indicating if computing a MAC
bool initialized; ///< Flag indicating hash has been initialized
size_t digestSize; ///< Digest size
class Context; ///< Opaque context type
Context* ctx; ///< Pointer to context.
};
/**
* SHA1 hash calculation interface abstraction class.
*/
class Crypto_SHA1 : public Crypto_Hash {
public:
virtual QStatus Init(const uint8_t* hmacKey = NULL, size_t keyLen = 0)
{
return Crypto_Hash::Init(SHA1, hmacKey, keyLen);
}
static const size_t DIGEST_SIZE = Crypto_Hash::SHA1_SIZE;
};
/**
* SHA256 hash calculation interface abstraction class.
*/
class Crypto_SHA256 : public Crypto_Hash {
public:
virtual QStatus Init(const uint8_t* hmacKey = NULL, size_t keyLen = 0)
{
return Crypto_Hash::Init(SHA256, hmacKey, keyLen);
}
static const size_t DIGEST_SIZE = Crypto_Hash::SHA256_SIZE;
};
/**
* This function uses one of more HMAC hashes to implement the PRF (Pseudorandom Function) defined
* in RFC 5246 and is used to expand a secret into an arbitrarily long block of data from which keys
* can be derived. Per the recommendation in RFC 5246 this function uses the SHA256 hash function.
*
* @param secret A keyblob containing the secret being expanded.
* @param label An ASCII string that is hashed in with the other data.
* @param seed Some random data
* @param out Output data
* @param outLen The required length of the output data.
*/
QStatus Crypto_PseudorandomFunction(const KeyBlob& secret, const char* label, const std::vector<uint8_t, SecureAllocator<uint8_t> >& seed, uint8_t* out, size_t outLen);
/**
* Secure Remote Password (SRP6) class. This implements the core algorithm for Secure Remote
* Password authentication protocol as defined in RFC 5054.
*/
class Crypto_SRP {
public:
/**
* Initialize the client side of SRP. The client is initialized with a string from the server
* that encodes the startup parameters.
*
* @param fromServer Hex-encoded parameter string from the server.
* @param toServer Returns a hex-encoded parameter string to be sent to the server.
*
* @return - ER_OK if the initialization was succesful.
* - ER_BAD_STRING_ENCODING if the hex-encoded parameter block is badly formed.
* - ER_CRYPTO_INSUFFICIENT_SECURITY if the parameters are not acceptable.
* - ER_CRYPTO_ILLEGAL_PARAMETERS if any parameters have illegal values.
*/
QStatus ClientInit(const qcc::String& fromServer, qcc::String& toServer);
/**
* Final phase of the client side .
*
* @param id The user use id to authenticate.
* @param pwd The password corresponding to the user id.
*
* @return ER_OK or an error status.
*/
QStatus ClientFinish(const qcc::String& id, const qcc::String& pwd);
/**
* Initialize the server side of SRP. The server is initialized with the user id and password
* and returns a hex-encoded string to be sent to the client that encodes the startup parameters.
*
* @param id The id of the user being authenticated.
* @param pwd The password corresponding to the user id.
* @param toClient Hex-encoded parameter string to be sent to the client.
*
* @return - ER_OK or an error status.
*/
QStatus ServerInit(const qcc::String& id, const qcc::String& pwd, qcc::String& toClient);
/**
* Initialize the server side of SRP using a hex-encoded verifier string that encodes the user name and
* password. Returns a hex-encoded string to be sent to the client that encodes the startup parameters.
*
* @param verifier An encoding of the user id and password that is used to verify the client.
* @param toClient Hex-encoded parameter string to be sent to the client.
*
* @return - ER_OK or an error status.
*/
QStatus ServerInit(const qcc::String& verifier, qcc::String& toClient);
/**
* Final phase of the server side of SRP. The server is provided with a string from the client
* that encodes the client's parameters.
*
* @param fromClient Hex-encoded parameter string from the client.
*
* @return - ER_OK if the initialization was succesful.
* - ER_BAD_STRING_ENCODING if the hex-encoded parameter block is badly formed.
* - ER_CRYPTO_ILLEGAL_PARAMETERS if any parameters have illegal values.
*/
QStatus ServerFinish(const qcc::String fromClient);
/**
* Get encoded verifier. The verifier can stored for future use by the server-side of the
* protocol without requiring knowledge of the password. This function can be called immediately
* after ServerInit() has been called.
*
* @return Returns the verifier string.
*/
qcc::String ServerGetVerifier();
/**
* Get the computed premaster secret. This function should be called after ServerFinish() or
* ClientFinish() to obtain the shared premaster secret.
*
* @param premaster Returns a key blob initialized with the premaster secret.
*/
void GetPremasterSecret(KeyBlob& premaster);
/**
* Constructor
*/
Crypto_SRP();
/**
* Destructor
*/
~Crypto_SRP();
/**
* Test interface runs the RFC 5246 test vector.
*/
QStatus TestVector();
private:
/**
* No copy constructor
*/
Crypto_SRP(const Crypto_SRP& other);
/**
* No assigment operator
*/
Crypto_SRP& operator=(const Crypto_SRP& other);
void ServerCommon(qcc::String& toClient);
class BN;
BN* bn;
};
/**
* ASN.1 encoding and decoding class. This implements encoding and decoding algorithms for
* DER-formatted ASN.1 string and related helper functions.
*/
class Crypto_ASN1 {
public:
/**
* Decode a DER formatted ASN1 data blob returning the decoded values as a variable length list
* of argument. The expected structure of the ASN1 data blob is described by the syntax
* parameter. The variable argument list must conform to the argument types for each syntactic
* element as defined below.
*
* 'i' ASN_INTEGER An integer of 4 bytes or less the argument must be a pointer to a uint32
*
* 'l' ASN_INTEGER An arbitrary length integer, the argument must be a pointer to a qcc::String
*
* 'o' ASN_OID An ASN encoded object id, the argument must be a pointer to a qcc::String
*
* 'x' ASN_OCTET An octet string, the argument must be a pointer to a qcc::String
*
* 'b' ASN_BITS A bit string, the argument must be a pointer to a qcc::String followe by a
* pointer to a size_t value to receive the bit length.
*
* 'z' ASN_BOOLEAN A boolean value, the argument must be a uint32. 0 is false, others true.
*
* 'n' ASN_NULL Null, there is no argument for this item
*
* 'u' ASN_UTF8 A utf8 string, the argument must be a pointer to a qcc::String
*
* 'a' ASN_ASCII A printable string, the argument must be a pointer to a qcc::String
*
* 'p' ASN_PRINTABLE A printable string, the argument must be a pointer to a qcc::String
*
* 't' ASN_UTC_TIME A UTC time string, the argument must be a pointer to a qcc::String
*
* 'T' ASN_GEN_TIME A Generic time string, the argument must be a pointer to a qcc::String
*
* '(' ASN_SEQ Indicates the start of a sequence, there are no arguments this item.
*
* ')' Indicates the end of a sequence, there are no arguments this item.
*
* '{' ASN_SET_OF Indicates the start of a set-of, there are no arguments this item.
*
* '}' Indicates the end of a set-of, there are no arguments this item.
*
* '[' ASN_TAGGED Indicates the start of an explicitly tagged type, there are no arguments this item.
*
* ']' Indicates the end of an explicitly tagged type, there are no arguments this item.
*
* '?' A single element that is extracted but not decoded, the argument must be a
* pointer to a qcc::String or NULL to ignore this item.
*
* '*' Zero or more optional elements up to the end of the enclosing sequence or set
* are skipped.
*
* '.' Elements up to the end of the enclosing sequence are extracted and returned.
* Argument must be a pointer to a qcc::String or NULL to ignore this item.
*
* '/' Before the final syntatic element of a sequence or set this indicates that
* the element is optional. If the element exists it is decoded. The argument
* must be a pointer to a qcc::String and type of the following element must
* be appropriate for this argument type. Note that is it not possible to
* distinguish between a missing element and a zero length element.
*
* 'c(...)' allows to insert a context specific information. This can be useful when handling optional fields.
* The value for this field must be an uint32 with value less than 32.
* Example: Snippet from X509 ASN.1 structure definition
* TBSCertificate ::= SEQUENCE {
* version [0] Version DEFAULT v1,
*
* }
* Decode("(c(i))",0,2))
*
* @param asn The input data for the encoding
* @param asnLen The length of the input data
* @param syntax The structure to use for the decoding operation.
* @param ... The output arguments as required by the syntax parameter to receive the
* decode values.
*
* @return ER_OK if the decode succeeded.
* An error status otherwise.
*
*/
static QStatus AJ_CALL Decode(const uint8_t* asn, size_t asnLen, const char* syntax, ...)
{
if (!syntax) {
return ER_BAD_ARG_1;
}
if (!asn) {
return ER_BAD_ARG_2;
}
va_list argp;
va_start(argp, syntax);
QStatus status = DecodeV(syntax, asn, asnLen, &argp);
va_end(argp);
return status;
}
/**
* Variation on Decode method that takes a qcc::String argument.
*
* @param asn The input string for the encoding
* @param syntax The structure to use for the decoding operation.
* @param ... The output arguments as required by the syntax parameter to receive the
* decode values.
*
* @return ER_OK if the decode succeeded.
* An error status otherwise.
*
*/
static QStatus AJ_CALL Decode(const qcc::String& asn, const char* syntax, ...)
{
if (!syntax) {
return ER_BAD_ARG_1;
}
va_list argp;
va_start(argp, syntax);
QStatus status = DecodeV(syntax, (const uint8_t*)asn.data(), asn.size(), &argp);
va_end(argp);
return status;
}
/**
* Encode a variable length list of arguments into an ASN1 data blob. The structure of the ASN1
* data blob is described by the syntax parameter. The variable argument list must conform to
* the argument types for each syntactic element as defined below.
*
* 'i' ASN_INTEGER An integer of 4 bytes or less the argument must be a uint32
*
* 'l' ASN_INTEGER An arbitrary length integer, the argument must be a pointer to a qcc::String
*
* 'o' ASN_OID An ASN encoded object id, the argument must be a pointer to a qcc::String
*
* 'x' ASN_OCTET An octet string, the argument must be a pointer to a qcc::String
*
* 'b' ASN_BITS A bit string, the argument must be a pointer to a qcc::String followed by a
* size_t value that specifies the bit length.
*
* 'z' ASN_BOOLEAN A boolean value, the argument must be a uint32. 0 is false, others true.
*
* 'n' ASN_NULL Null, there is no argument for this item
*
* 'u' ASN_UTF8 A utf8 string, the argument must be a pointer to a qcc::String
*
* 'a' ASN_ASCII A printable string, the argument must be a pointer to a qcc::String
*
* 'p' ASN_PRINTABLE A printable string, the argument must be a pointer to a qcc::String
*
* 't' ASN_UTC_TIME A UTC time string, the argument must be a pointer to a qcc::String
*
* '(' ASN_SEQ Indicates the start of a sequence, there are no arguments this item.
*
* ')' Indicates the end of a sequence, there are no arguments this item.
*
* '{' ASN_SET_OF Indicates the start of a set-of, there are no arguments this item.
*
* '}' Indicates the end of a set-of, there are no arguments this item.
*
* 'R' inserts raw data as is. This allows to include previously formatted ASN strings to be inserted
* The argument for this must be qcc::String
* 'c(...)' allows to insert a context specific information. This can be useful when handling optional fields.
* The value for this field must be an uint32 with value less than 32.
* Example: Snippet from X509 ASN.1 structure definition
* TBSCertificate ::= SEQUENCE {
* version [0] Version DEFAULT v1,
*
* }
* Encode("(c(i))",0,2))
*
*
* @param asn The output string for the encoding
* @param syntax The structure to use for the encoding operation.
* @param ... The input arguments as required by the syntax parameter
*
* @return ER_OK if the encode succeeded.
* An error status otherwise.
*/
static QStatus AJ_CALL Encode(qcc::String& asn, const char* syntax, ...)
{
if (!syntax) {
return ER_FAIL;
}
va_list argp;
va_start(argp, syntax);
QStatus status = EncodeV(syntax, asn, &argp);
va_end(argp);
return status;
}
/**
* Decode a PEM base-64 ANSI string to binary.
*
* @param b64 The base-64 string to decode.
* @param bin The binary output of the decoding.
*
* @return ER_OK if the decode succeeded.
* An error status otherwise.
*/
static QStatus AJ_CALL DecodeBase64(const qcc::String& b64, qcc::String& bin);
/**
* Decode a PEM base-64 ANSI string to a vector of bytes.
*
* @param b64 The base-64 string to decode.
* @param bin The vector of bytes output of the decoding.
*
* @return ER_OK if the decode succeeded.
* An error status otherwise.
*/
static QStatus AJ_CALL DecodeBase64(const qcc::String& b64, std::vector<uint8_t>& bin);
/**
* Encode a binary string as a PEM base-64 ANSI string.
*
* @param bin The binary string to encode.
* @param b64 The base-64 output of the decoding.
*
* @return ER_OK if the encode succeeded.
* An error status otherwise.
*/
static QStatus AJ_CALL EncodeBase64(const qcc::String& bin, qcc::String& b64);
/**
* Encode a vector of bytes as a PEM base-64 ANSI string.
*
* @param bin The vector of bytes to encode.
* @param b64 The base-64 output of the decoding.
*
* @return ER_OK if the encode succeeded.
* An error status otherwise.
*/
static QStatus AJ_CALL EncodeBase64(const std::vector<uint8_t>& bin, qcc::String& b64);
/*
* Render ASN.1 as a "human" readable string
*/
static qcc::String AJ_CALL ToString(const uint8_t* asn, size_t len, size_t indent = 0);
private:
static const uint8_t ASN_BOOLEAN = 0x01;
static const uint8_t ASN_INTEGER = 0x02;
static const uint8_t ASN_BITS = 0x03;
static const uint8_t ASN_OCTETS = 0x04;
static const uint8_t ASN_NULL = 0x05;
static const uint8_t ASN_OID = 0x06;
static const uint8_t ASN_UTF8 = 0x0C;
static const uint8_t ASN_SEQ = 0x10;
static const uint8_t ASN_SET_OF = 0x11;
static const uint8_t ASN_PRINTABLE = 0x13;
static const uint8_t ASN_ASCII = 0x16;
static const uint8_t ASN_UTC_TIME = 0x17;
static const uint8_t ASN_GEN_TIME = 0x18;
static const uint8_t ASN_CONTEXT_SPECIFIC = 0x80;
static const uint8_t ASN_CONTEXT_SPECIFIC_CONSTRUCTED = 0xA0;
static const uint8_t ASN_CONSTRUCTED_ENCODING = 0x20;
static QStatus DecodeV(const char*& syntax, const uint8_t* asn, size_t asnLen, va_list* argpIn);
static QStatus EncodeV(const char*& syntax, qcc::String& asn, va_list* argpIn);
static qcc::String DecodeOID(const uint8_t* p, size_t len);
static QStatus EncodeOID(qcc::String& asn, const qcc::String& oid);
static bool DecodeLen(const uint8_t*& p, const uint8_t* eod, size_t& l);
static void EncodeLen(qcc::String& asn, size_t l);
};
/**
* Call platform specific API to get cryptographically random data.
*
* @param data A buffer to receive the pseuod random number data.
* @param len The length of the buffer.
*
* @return ER_OK if a random number was succesfully generated.
*/
QStatus Crypto_GetRandomBytes(uint8_t* data, size_t len);
/**
* Class for random number generator.
*/
class Crypto_Rand {
public:
Crypto_Rand() { };
virtual QStatus Seed(uint8_t* seed, size_t size) = 0;
virtual QStatus Generate(uint8_t* rand, size_t size) = 0;
virtual ~Crypto_Rand() { };
};
class Crypto_DRBG : public Crypto_Rand {
public:
static const size_t KEYLEN = Crypto_AES::AES128_SIZE;
static const size_t OUTLEN = sizeof (Crypto_AES::Block);
static const size_t SEEDLEN = KEYLEN + OUTLEN;
static const uint32_t RESEED_COUNT = 0x80000000;
Crypto_DRBG();
virtual QStatus Seed(uint8_t* seed, size_t size);
virtual QStatus Generate(uint8_t* rand, size_t size);
virtual ~Crypto_DRBG();
private:
void Update(uint8_t data[SEEDLEN]);
/**
* Opaque type for the internal context
*/
struct Context;
/**
* Private internal context
*/
Context* ctx;
};
/**
* Compare two buffers in constant time. For any two inputs buf1 and buf2, and
* fixed count, the function will use the same number of cycles.
*
* @param buf1 The first buffer to compare.
* @param buf2 The second buffer to compare.
* @param count The number of bytes to compare.
*
* @return 0 if the first count bytes of buf1 and buf2 are equal, nonzero otherwise.
*
*/
int Crypto_Compare(const void* buf1, const void* buf2, size_t count);
}
#endif
|