typedef struct ssl3_record_st {
…
unsigned int length; /* How many bytes available */
unsigned char *data; /* pointer to the record data */
…
} SSL3_RECORD;
int dtls1_process_heartbeat(SSL *s) {
unsigned char *p = &s->s3->rrec.data[0], *pl;
unsigned int payload;
unsigned int padding = 16; /* Use minimum padding */
/* Read type and payload length first */
hbtype = *p++; n2s(p, payload); pl = p;
unsigned char *buffer, *bp;
/* Allocate memory for the response, size is 1 byte
* message type, plus 2 bytes payload length, plus
* payload, plus padding
*/
buffer = OPENSSL_malloc(1 + 2 + payload + padding); bp = buffer;
/* Enter response type, length and copy payload */
*bp++ = TLS1_HB_RESPONSE; s2n(payload, bp); memcpy(bp, pl, payload);
}
static void *(*malloc_func)(size_t)
= malloc
static void *default_malloc_ex(size_t num, const char *file, int line) {
return malloc_func(num);
}
static void *(*malloc_ex_func)(size_t, const char *file, int line)
= default_malloc_ex;
#define OPENSSL_malloc(num) CRYPTO_malloc((int)num,__FILE__,__LINE__)
unsigned char cleanse_ctr = 0
void *CRYPTO_malloc(int num, const char *file, int line) {
void *ret = NULL;
if (num <= 0) return NULL;
allow_customize = 0;
if (malloc_debug_func != NULL) {
allow_customize_debug = 0;
malloc_debug_func(NULL, num, file, line, 0);
}
ret = malloc_ex_func(num,file,line);
#ifdef LEVITTE_DEBUG_MEM
fprintf(stderr, "LEVITTE_DEBUG_MEM: > 0x%p (%d)\n", ret, num);
#endif
if (malloc_debug_func != NULL)
malloc_debug_func(ret, num, file, line, 1);
#ifndef OPENSSL_CPUID_OBJ
/* Create a dependency on the value of 'cleanse_ctr' so our memory
* sanitisation function can't be optimised out. NB: We only do
* this for >2Kb so the overhead doesn't bother us. */
if(ret && (num > 2048)) {
extern unsigned char cleanse_ctr;
((unsigned char *)ret)[0] = cleanse_ctr;
}
#endif
return ret;
}
int ssl3_setup_read_buffer(SSL *s) {
if (s->s3->rbuf.buf == NULL) {
if ((p=freelist_extract(s->ctx, 1, len)) == NULL)
goto err;
s->s3->rbuf.buf = p;
}
}
int ssl3_release_read_buffer(SSL *s) {
if (s->s3->rbuf.buf != NULL) {
freelist_insert(s->ctx, 1, s->s3->rbuf.len, s->s3->rbuf.buf);
s->s3->rbuf.buf = NULL;
}
}
int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) {
if (s->s3->rbuf.buf == NULL) /* Not initialized yet */
if (!ssl3_setup_read_buffer(s))
return(-1);
if (!peek) {
if (s->mode & SSL_MODE_RELEASE_BUFFERS)
ssl3_release_read_buffer(s);
}
}
unsigned char cleanse_ctr = 0;
void OPENSSL_cleanse(void *ptr, size_t len) {
unsigned char *p = ptr;
size_t loop = len, ctr = cleanse_ctr;
while (loop--) {
*(p++) = (unsigned char)ctr;
ctr += (17 + ((size_t)p & 0xF));
}
p = memchr(ptr, (unsigned char)ctr, len);
if (p)
ctr += (63 + (size_t)p);
cleanse_ctr = (unsigned char)ctr;
}
void OPENSSL_cleanse(void *ptr, size_t len) {
explicit_bzero(ptr, len);
}
int OPENSSL_strcasecmp(const char *str1, const char *str2) {
#if defined(OPENSSL_IMPLEMENTS_strncasecmp)
return OPENSSL_strncasecmp(str1, str2, (size_t) - 1);
#else
return strcasecmp(str1, str2);
#endif
}
int OPENSSL_memcmp(const void *v1, const void *v2, size_t n) {
const unsigned char *c1 = v1, *c2 = v2;
int ret = 0;
while (n && (ret = *c1 - *c2) == 0) n--, c1++, c2++;
return ret;
}
int OPENSSL_strncasecmp(const char *str1, const char *str2, size_t n) {
#if defined(OPENSSL_IMPLEMENTS_strncasecmp)
while (*str1 && *str2 && n) {
int res = toupper(*str1) - toupper(*str2);
if (res) return res < 0 ? -1 : 1;
str1++; str2++; n--;
}
if (n == 0)
return 0;
if (*str1)
return 1;
if (*str2)
return -1;
return 0;
#else
/* Recursion hazard warning! Whenever strncasecmp is #defined as
* OPENSSL_strncasecmp, OPENSSL_IMPLEMENTS_strncasecmp must be
* defined as well. */
return strncasecmp(str1, str2, n);
#endif
}
Well, even if time() isn't random
your RSA private key is probably pretty random…
BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx) {
if ((RAND_status() == 0) && rsa->d != NULL && rsa->d->d != NULL) {
/* if PRNG is not properly seeded, resort to secret
* exponent as unpredictable seed */
RAND_add(rsa->d->d, rsa->d->dmax * sizeof rsa->d->d[0], 0.0);
}
}
Digests are probably pretty random too;
let's toss those into the rng too !
int DSA_sign(int type, const unsigned char *dgst, int unsigned int *siglen, DSA *dsa) {
…
RAND_seed(dgst, dlen);
…
}
void aes_gcm_cleanup(EVP_CIPHER_CTX *c) {
EVP_AES_GCM_CTX *gctx = c->cipher_data;
OPENSSL_cleanse(&gctx->gcm, sizeof(gctx->gcm));
}
void aes_gcm_cleanup(EVP_CIPHER_CTX *c) {
EVP_AES_GCM_CTX *gctx = c->cipher_data;
OPENSSL_cleanse(gctx, sizeof(*gctx));
}
ssl/ssl.h: long time;
ssl/ssl.h:long SSL_SESSION_get_time(const SSL_SESSION *s);
ssl/ssl.h:long SSL_SESSION_set_time(SSL_SESSION *s, long t);
ssl/ssl_sess.c: ss->time=(unsigned long)time(NULL);
ssl/ssl_sess.c: if (ret->timeout < (long)(time(NULL) - ret->time)) /* timeout */
ssl/ssl_sess.c:long SSL_SESSION_get_time(const SSL_SESSION *s)
ssl/ssl_sess.c:long SSL_SESSION_set_time(SSL_SESSION *s, long t)
ssl/ssl_sess.c: long time;
crypto/o_time.c: long time_jd;
crypto/o_time.c: long time_jd;
apps/s_time.c: long finishtime=0;
apps/s_time.c: finishtime=(long)time(NULL)+maxTime;
apps/s_time.c: if (finishtime < (long)time(NULL)) break;
apps/s_time.c: i=(int)((long)time(NULL)-finishtime+maxTime);
apps/s_time.c: printf( "%d connections in %ld real seconds,
%ld bytes read per connection\n",nConn,
(long)time(NULL)-finishtime+maxTime,bytes_read/nConn);
apps/s_time.c: finishtime=(long)time(NULL)+maxTime;
apps/s_time.c: if (finishtime < (long)time(NULL)) break;
apps/s_time.c: printf( "%d connections in %ld real seconds,
%ld bytes read per connection\n",nConn,
(long)time(NULL)-finishtime+maxTime,bytes_read/nConn);
$ rgrep /home/eay
util/bat.sh:$infile="/home/eay/ssl/SSLeay/MINFO";
test/methtest.c: METH_arg(tmp2,METH_TYPE_DIR,"/home/eay/.CAcerts");
test/methtest.c: METH_arg(tmp2,METH_TYPE_DIR,"/home/eay/SSLeay/certs");
test/methtest.c: METH_arg(tmp,METH_TYPE_DIR,"/home/eay/.mycerts");
test/methtest.c: METH_arg(tmp,METH_TYPE_FILE,"/home/eay/.mycerts/primary.pem");
12 years ago, old_des.h was used to provide compatibility with libdes.
The man page says “Compatibility des_ functions are provided for a short while” and indeed even the original commit message says “The compatibility functions will be removed in some future release, at the latest in version 1.0.” So here we are, a short while later.
Now I’ve only been an OpenBSD developer for 11 years, one year less than this header has existed, but in that brief time, I’ve learned a thing or two about deleting obsolete code. It doesn’t delete itself. And worse, people will continue using it until you force them onto a better path.
So the OpenSSL codebase does “get the time, add it as a random seed” in a bunch of places inside the TLS engine, to try to keep entropy high. I wonder if their moto is “If you can’t solve a problem, at least try to do it badly
Ok, there was a need for OPENSSL_cleanse() instead of bzero() to prevent supposedly smart compilers from optimizing memory cleanups away. Understood.
Ok, in case of an hypothetically super smart compiler, OPENSSL_cleanse() had to be convoluted enough for the compiler not to recognize that this was actually bzero() in disguise. Understood.
But then why there had been optimized assembler versions of OPENSSL_cleanse() is beyond me. Did someone not trust the C obfuscation?
Remove unused ssl utils
This code is the reason perl has a name as a write only language.
Do you really want to build OpenSSL for 16-bit Windows? Well, we don’t.
Remove non-posix support. Why is OPENSSL_isservice even here? Is this a crypto library or a generic platform abstraction library? “A hack to make Visual C++ 5.0 work correctly” … time to upgrade.
Nuke OPENSSL_NO_SOCK since any half sane operating system has sockets.
T.61 was proposed in 93. Utf8 later the same year. utf8 was recommended from 94. 2004 OpenSSL caught up with the recommendation, and decided to go against it to be compatible with Netscape Navigator. Which at that time had a massive 2% of the market. 2005 The behaviour of the openssl binaries were "fixed" by changing the config file. 2014 the default still hasn't been changed, 20 years after the original deprecation of T.61 in x509 standards. I love the speed with which this evolves.
H = SHA1(DER(public_key))
H' = H[0..10]
address = base32(H')[0..16]
H = SHA1(DER(public_key))
H' = H[0..10]
address = base32(H')[0..16]
int crypto_digest(char *digest, const char *m, size_t len) {
tor_assert(m);
tor_assert(digest);
return (SHA1((const unsigned char*)m,len,(unsigned char*)digest) == NULL);
}
void base32_encode(char *dest, size_t destlen, const char *src, size_t srclen) {
unsigned int i, v, u;
size_t nbits = srclen * 8, bit;
tor_assert(srclen < SIZE_T_CEILING/8);
tor_assert((nbits%5) == 0); /* We need an even multiple of 5 bits. */
tor_assert((nbits/5)+1 <= destlen); /* We need enough space. */
tor_assert(destlen < SIZE_T_CEILING);
for (i=0,bit=0; bit < nbits; ++i, bit+=5) {
/* set v to the 16-bit value starting at src[bits/8], 0-padded. */
v = ((uint8_t)src[bit/8]) << 8;
if (bit+5 < nbits) v += (uint8_t)src[(bit/8)+1];
/* set u to the 5-bit value at the bit'th bit of src. */
u = (v >> (11-(bit%8))) & 0x1F;
dest[i] = BASE32_CHARS[u];
}
dest[i] = '\0';
}
int crypto_pk_get_digest(crypto_pk_t *pk, char *digest_out) {
unsigned char *buf = NULL;
int len;
len = i2d_RSAPublicKey(pk->key, &buf);
if (len < 0 || buf == NULL)
return -1;
if (crypto_digest(digest_out, (char*)buf, len) < 0) {
OPENSSL_free(buf);
return -1;
}
OPENSSL_free(buf);
return 0;
}
#define REND_SERVICE_ID_LEN_BASE32 16
#define REND_SERVICE_ID_LEN 10
#define DIGEST_LEN 20
int rend_get_service_id(crypto_pk_t *pk, char *out) {
char buf[DIGEST_LEN];
tor_assert(pk);
if (crypto_pk_get_digest(pk, buf) < 0)
return -1;
base32_encode(out, REND_SERVICE_ID_LEN_BASE32+1, buf, REND_SERVICE_ID_LEN);
return 0;
}