| // Copyright 2011 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| // Author: Marius Schilder |
| // |
| // Lightweight C crypto library for sha256, hmac-sha256, DH, |
| // RSA2K-SHA256-PKCS15, PRNG, sha1, hmac-sha1, RSA2K-SHA1-PKCS15. |
| // |
| // Plain C, no system calls, no malloc. |
| |
| #pragma once |
| |
| #include <inttypes.h> |
| #include <zircon/compiler.h> |
| |
| #define clBIGNUMBYTES 256 // 2048 bit key length max |
| #define clBIGNUMWORDS (clBIGNUMBYTES / sizeof(uint32_t)) |
| |
| __BEGIN_CDECLS |
| |
| struct clHASH_CTX; // forward decl. |
| |
| // RSA interface ---------------------------------------- |
| |
| typedef struct clBignumModulus { |
| int size; // Length of n[] in bytes; |
| int nwords; // Length of n[] in number of uint32_t |
| uint32_t n0inv; // -1 / n[0] mod 2^32 |
| uint32_t n[clBIGNUMWORDS]; // modulus as little endian array |
| uint32_t rr[clBIGNUMWORDS]; // 2^(2*32*nwords) mod n as little endian array |
| } clBignumModulus; |
| |
| // PKCS1.5 signature verify. |
| // signature_len must be key->size. |
| // Returns 1 if OK. Trashes hash. |
| int clRSA2K_verify(const clBignumModulus* key, |
| const uint8_t* signature, |
| const int signature_len, |
| struct clHASH_CTX* hash /* not const! */); |
| |
| // Generic hash interface ---------------------------------------- |
| |
| typedef struct clHASH_vtab { |
| void (* const init)(struct clHASH_CTX*); |
| void (* const update)(struct clHASH_CTX*, const void*, int); |
| const uint8_t* (* const final)(struct clHASH_CTX*); |
| void (* const _transform)(struct clHASH_CTX*); |
| const int size; |
| const uint8_t* _2Kpkcs15hashpad; // hash of 2K bit padding. |
| } clHASH_vtab; |
| |
| typedef struct clHASH_CTX { |
| const clHASH_vtab* f; |
| uint64_t count; |
| uint8_t buf[64]; |
| uint32_t state[8]; |
| } clHASH_CTX; |
| |
| #define clHASH_init(ctx) (ctx)->f->init(ctx) |
| #define clHASH_update(ctx, data, len) (ctx)->f->update(ctx, data, len) |
| #define clHASH_final(ctx) (ctx)->f->final(ctx) |
| #define clHASH_size(ctx) (ctx)->f->size |
| |
| // Generic hmac interface ---------------------------------------- |
| |
| typedef struct clHMAC_CTX { |
| clHASH_CTX hash; |
| uint8_t opad[64]; |
| } clHMAC_CTX; |
| |
| #define clHMAC_update(ctx, data, len) clHASH_update(&(ctx)->hash, data, len) |
| #define clHMAC_size(ctx) clHASH_size(&(ctx)->hash) |
| const uint8_t* clHMAC_final(clHMAC_CTX* ctx); |
| |
| // SHA1 interface ---------------------------------------------- |
| |
| #define clSHA1_DIGEST_SIZE 20 |
| typedef clHASH_CTX clSHA1_CTX; |
| |
| void clSHA1_init(clSHA1_CTX* ctx); |
| void clHMAC_SHA1_init(clHMAC_CTX* ctx, const void* key, int len); |
| const uint8_t* clSHA1(const void* data, int len, uint8_t* digest); |
| |
| // SHA256 interface -------------------------------------------- |
| |
| #define clSHA256_DIGEST_SIZE 32 |
| typedef clHASH_CTX clSHA256_CTX; |
| |
| void clSHA256_init(clSHA256_CTX* ctx); |
| void clHMAC_SHA256_init(clHMAC_CTX* ctx, const void* key, int len); |
| const uint8_t* clSHA256(const void* data, int len, uint8_t* digest); |
| |
| // Safe compare interface -------------------------------- |
| |
| // Returns 0 if equal. |
| // Only fixed timing if arrays are of same length! |
| int clEqual(const uint8_t* a, int a_len, const uint8_t* b, int b_len); |
| |
| // DH interface -------------------------------------------- |
| |
| // Computes 2 ** x into out. x and out bigendian byte strings. |
| // out must be able to hold mod->size bytes. |
| // Return 0 on error. (invalid value for x). |
| int clDHgenerate(const clBignumModulus* mod, |
| const uint8_t* x, const int size_x, |
| uint8_t* out); |
| |
| // Computes gy ** x into out. gy, x, and out bigendian byte strings. |
| // size_gy must be mod->size. |
| // Returns 0 on error. (invalid size_gy, gy, x). |
| int clDHcompute(const clBignumModulus* mod, |
| const uint8_t* gy, const int size_gy, |
| const uint8_t* x, const int size_x, |
| uint8_t* out); |
| |
| // PRNG interface -------------------------------------------- |
| |
| typedef struct clPRNG_CTX { |
| uint8_t v[clSHA256_DIGEST_SIZE * 2]; |
| int index; |
| } clPRNG_CTX; |
| |
| // Initial seeding. |
| void clPRNG_init(clPRNG_CTX* ctx, const void* data, int size); |
| |
| // Add entropy to state. Non-destructive, additive. |
| // Best to call at least once before calling clPRNG_draw(). |
| void clPRNG_entropy(clPRNG_CTX* ctx, const void* data, int size); |
| |
| // Generate size bytes random and advance state. |
| // Beware: out value covers entire spectrum so all 0 is possible. |
| void clPRNG_draw(clPRNG_CTX* ctx, void* out, int size); |
| |
| __END_CDECLS |