1// Copyright 2011 Google Inc. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// Author: Marius Schilder
16//
17// Lightweight C crypto library for sha256, hmac-sha256, DH,
18// RSA2K-SHA256-PKCS15, PRNG, sha1, hmac-sha1, RSA2K-SHA1-PKCS15.
19//
20// Plain C, no system calls, no malloc.
21
22#pragma once
23
24#include <inttypes.h>
25#include <zircon/compiler.h>
26
27#define clBIGNUMBYTES 256      // 2048 bit key length max
28#define clBIGNUMWORDS (clBIGNUMBYTES / sizeof(uint32_t))
29
30__BEGIN_CDECLS
31
32struct clHASH_CTX;  // forward decl.
33
34// RSA interface ----------------------------------------
35
36typedef struct clBignumModulus {
37  int size;                    // Length of n[] in bytes;
38  int nwords;                  // Length of n[] in number of uint32_t
39  uint32_t n0inv;              // -1 / n[0] mod 2^32
40  uint32_t n[clBIGNUMWORDS];   // modulus as little endian array
41  uint32_t rr[clBIGNUMWORDS];  // 2^(2*32*nwords) mod n as little endian array
42} clBignumModulus;
43
44// PKCS1.5 signature verify.
45// signature_len must be key->size.
46// Returns 1 if OK. Trashes hash.
47int clRSA2K_verify(const clBignumModulus* key,
48                   const uint8_t* signature,
49                   const int signature_len,
50                   struct clHASH_CTX* hash /* not const! */);
51
52// Generic hash interface ----------------------------------------
53
54typedef struct clHASH_vtab {
55  void (* const init)(struct clHASH_CTX*);
56  void (* const update)(struct clHASH_CTX*, const void*, int);
57  const uint8_t* (* const final)(struct clHASH_CTX*);
58  void (* const _transform)(struct clHASH_CTX*);
59  const int size;
60  const uint8_t* _2Kpkcs15hashpad;  // hash of 2K bit padding.
61} clHASH_vtab;
62
63typedef struct clHASH_CTX {
64  const clHASH_vtab* f;
65  uint64_t count;
66  uint8_t buf[64];
67  uint32_t state[8];
68} clHASH_CTX;
69
70#define clHASH_init(ctx) (ctx)->f->init(ctx)
71#define clHASH_update(ctx, data, len) (ctx)->f->update(ctx, data, len)
72#define clHASH_final(ctx) (ctx)->f->final(ctx)
73#define clHASH_size(ctx) (ctx)->f->size
74#define clHASH_MAX_DIGEST_SIZE 32
75
76// Generic hmac interface ----------------------------------------
77
78typedef struct clHMAC_CTX {
79  clHASH_CTX hash;
80  uint8_t opad[64];
81} clHMAC_CTX;
82
83#define clHMAC_update(ctx, data, len) clHASH_update(&(ctx)->hash, data, len)
84#define clHMAC_size(ctx) clHASH_size(&(ctx)->hash)
85const uint8_t* clHMAC_final(clHMAC_CTX* ctx);
86
87// SHA1 interface ----------------------------------------------
88
89#define clSHA1_DIGEST_SIZE 20
90typedef clHASH_CTX clSHA1_CTX;
91
92void clSHA1_init(clSHA1_CTX* ctx);
93void clHMAC_SHA1_init(clHMAC_CTX* ctx, const void* key, int len);
94const uint8_t* clSHA1(const void* data, int len, uint8_t* digest);
95
96// SHA256 interface --------------------------------------------
97
98#define clSHA256_DIGEST_SIZE 32
99typedef clHASH_CTX clSHA256_CTX;
100
101void clSHA256_init(clSHA256_CTX* ctx);
102void clHMAC_SHA256_init(clHMAC_CTX* ctx, const void* key, int len);
103const uint8_t* clSHA256(const void* data, int len, uint8_t* digest);
104
105// Safe compare interface --------------------------------
106
107// Returns 0 if equal.
108// Only fixed timing if arrays are of same length!
109int clEqual(const uint8_t* a, int a_len, const uint8_t* b, int b_len);
110
111// DH interface --------------------------------------------
112
113// Computes 2 ** x into out. x and out bigendian byte strings.
114// out must be able to hold mod->size bytes.
115// Return 0 on error. (invalid value for x).
116int clDHgenerate(const clBignumModulus* mod,
117                 const uint8_t* x, const int size_x,
118                 uint8_t* out);
119
120// Computes gy ** x into out. gy, x, and out bigendian byte strings.
121// size_gy must be mod->size.
122// Returns 0 on error. (invalid size_gy, gy, x).
123int clDHcompute(const clBignumModulus* mod,
124                const uint8_t* gy, const int size_gy,
125                const uint8_t* x, const int size_x,
126                uint8_t* out);
127
128// PRNG interface --------------------------------------------
129
130typedef struct clPRNG_CTX {
131  uint8_t v[clSHA256_DIGEST_SIZE * 2];
132  int index;
133} clPRNG_CTX;
134
135// Initial seeding.
136void clPRNG_init(clPRNG_CTX* ctx, const void* data, int size);
137
138// Add entropy to state. Non-destructive, additive.
139// Best to call at least once before calling clPRNG_draw().
140void clPRNG_entropy(clPRNG_CTX* ctx, const void* data, int size);
141
142// Generate size bytes random and advance state.
143// Beware: out value covers entire spectrum so all 0 is possible.
144void clPRNG_draw(clPRNG_CTX* ctx, void* out, int size);
145
146__END_CDECLS
147