Move RSA key generation into the wrappers.

This commit is contained in:
Guus Sliepen 2008-12-14 12:47:26 +00:00
parent 911c05f873
commit 551cd19406
18 changed files with 413 additions and 68 deletions

View file

@ -55,7 +55,7 @@ static struct {
};
static bool nametocipher(const char *name, int *algo, int *mode) {
int i;
size_t i;
for(i = 0; i < sizeof ciphertable / sizeof *ciphertable; i++) {
if(ciphertable[i].name && !strcasecmp(name, ciphertable[i].name)) {
@ -69,7 +69,7 @@ static bool nametocipher(const char *name, int *algo, int *mode) {
}
static bool nidtocipher(int nid, int *algo, int *mode) {
int i;
size_t i;
for(i = 0; i < sizeof ciphertable / sizeof *ciphertable; i++) {
if(nid == ciphertable[i].nid) {
@ -83,7 +83,7 @@ static bool nidtocipher(int nid, int *algo, int *mode) {
}
static bool ciphertonid(int algo, int mode, int *nid) {
int i;
size_t i;
for(i = 0; i < sizeof ciphertable / sizeof *ciphertable; i++) {
if(algo == ciphertable[i].algo && mode == ciphertable[i].mode) {

View file

@ -24,6 +24,10 @@
#include <gcrypt.h>
#define CIPHER_MAX_BLOCK_SIZE 32
#define CIPHER_MAX_IV_SIZE 16
#define CIPHER_MAX_KEY_SIZE 32
typedef struct cipher {
gcry_cipher_hd_t handle;
char *key;

View file

@ -24,6 +24,8 @@
#include <gcrypt.h>
#define DIGEST_MAX_SIZE 64
typedef struct digest {
int algo;
int nid;

View file

@ -26,7 +26,7 @@
#include "logger.h"
#include "rsa.h"
// Base64 encoding/decoding tables
// Base64 decoding table
static const uint8_t b64d[128] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
@ -53,8 +53,6 @@ static const uint8_t b64d[128] = {
0xff, 0xff
};
static const char b64e[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// PEM encoding/decoding functions
static bool pem_decode(FILE *fp, const char *header, uint8_t *buf, size_t size, size_t *outsize) {

222
src/gcrypt/rsagen.c Normal file
View file

@ -0,0 +1,222 @@
/*
rsagen.c -- RSA key generation and export
Copyright (C) 2008 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id$
*/
#include "system.h"
#include <gcrypt.h>
#include "rsagen.h"
#if 0
// Base64 encoding table
static const char b64e[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// PEM encoding
static bool pem_encode(FILE *fp, const char *header, uint8_t *buf, size_t size) {
bool decode = false;
char line[1024];
uint32_t word = 0;
int shift = 0;
size_t i, j = 0;
fprintf(fp, "-----BEGIN %s-----\n", header);
for(i = 0; i < size; i += 3) {
if(i <= size - 3) {
word = buf[i] << 16 | buf[i + 1] << 8 | buf[i + 2];
} else {
word = buf[i] << 16;
if(i == size - 2)
word |= buf[i + 1] << 8;
}
line[j++] = b64e[(word >> 18) ];
line[j++] = b64e[(word >> 12) & 0x3f];
line[j++] = b64e[(word >> 6) & 0x3f];
line[j++] = b64e[(word ) & 0x3f];
if(j >= 64) {
line[j++] = '\n';
line[j] = 0;
fputs(line, fp);
j = 0;
}
}
if(size % 3 > 0) {
if(size % 3 > 1)
line[j++] = '=';
line[j++] = '=';
}
if(j) {
line[j++] = '\n';
line[j] = 0;
fputs(line, fp);
}
fprintf(fp, "-----END %s-----\n", header);
return true;
}
// BER encoding functions
static bool ber_write_id(uint8_t **p, size_t *buflen, int id) {
if(*buflen <= 0)
return false;
if(id >= 0x1f) {
while(id) {
if(*buflen <= 0)
return false;
(*buflen)--;
**p = id & 0x7f;
id >>= 7;
if(id)
**p |= 0x80;
(*p)++;
}
} else {
(*buflen)--;
*(*p)++ = id;
}
return true;
}
static bool ber_write_len(uint8_t **p, size_t *buflen, size_t len) {
do {
if(*buflen <= 0)
return false;
(*buflen)--;
**p = len & 0x7f;
len >>= 7;
if(len)
**p |= 0x80;
(*p)++;
} while(len);
return true;
}
static bool ber_write_sequence(uint8_t **p, size_t *buflen, uint8_t *seqbuf, size_t seqlen) {
if(!ber_write_id(p, buflen, 0x10) || !ber_write_len(p, buflen, seqlen) || *buflen < seqlen)
return false;
memcpy(*p, seqbuf, seqlen);
*p += seqlen;
*buflen -= seqlen;
return true;
}
static bool ber_write_mpi(uint8_t **p, size_t *buflen, gcry_mpi_t mpi) {
uint8_t tmpbuf[1024];
size_t tmplen = sizeof tmpbuf;
gcry_error_t err;
err = gcry_mpi_aprint(GCRYMPI_FMT_USG, &tmpbuf, &tmplen, mpi);
if(err)
return false;
if(!ber_write_id(p, buflen, 0x02) || !ber_write_len(p, buflen, tmplen) || *buflen < tmplen)
return false;
memcpy(*p, tmpbuf, tmplen);
*p += tmplen;
*buflen -= tmplen;
return true;
}
// Write PEM RSA keys
bool rsa_write_pem_public_key(rsa_t *rsa, FILE *fp) {
uint8_t derbuf1[8096];
uint8_t derbuf2[8096];
uint8_t *derp1 = derbuf1;
uint8_t *derp2 = derbuf2;
size_t derlen1 = sizeof derbuf1;
size_t derlen2 = sizeof derbuf2;
if(!ber_write_mpi(&derp1, &derlen1, &rsa->n)
|| !ber_write_mpi(&derp1, &derlen1, &rsa->e)
|| !ber_write_sequence(&derp2, &derlen2, derbuf1, derlen1)) {
logger(LOG_ERR, _("Error while encoding RSA public key"));
return false;
}
if(!pem_encode(fp, "RSA PUBLIC KEY", derbuf2, derlen2)) {
logger(LOG_ERR, _("Unable to write RSA public key: %s"), strerror(errno));
return false;
}
return true;
}
bool rsa_write_pem_private_key(rsa_t *rsa, FILE *fp) {
uint8_t derbuf1[8096];
uint8_t derbuf2[8096];
uint8_t *derp1 = derbuf1;
uint8_t *derp2 = derbuf2;
size_t derlen1 = sizeof derbuf1;
size_t derlen2 = sizeof derbuf2;
if(!ber_write_mpi(&derp1, &derlen1, &bits)
|| ber_write_mpi(&derp1, &derlen1, &rsa->n) // modulus
|| ber_write_mpi(&derp1, &derlen1, &rsa->e) // public exponent
|| ber_write_mpi(&derp1, &derlen1, &rsa->d) // private exponent
|| ber_write_mpi(&derp1, &derlen1, &p)
|| ber_write_mpi(&derp1, &derlen1, &q)
|| ber_write_mpi(&derp1, &derlen1, &exp1)
|| ber_write_mpi(&derp1, &derlen1, &exp2)
|| ber_write_mpi(&derp1, &derlen1, &coeff))
logger(LOG_ERR, _("Error while encoding RSA private key"));
return false;
}
if(!pem_encode(fp, "RSA PRIVATE KEY", derbuf2, derlen2)) {
logger(LOG_ERR, _("Unable to write RSA private key: %s"), strerror(errno));
return false;
}
return true;
}
#endif
bool rsa_write_pem_public_key(rsa_t *rsa, FILE *fp) {
return false;
}
bool rsa_write_pem_private_key(rsa_t *rsa, FILE *fp) {
return false;
}
bool rsa_generate(rsa_t *rsa, size_t bits, unsigned long exponent) {
fprintf(stderr, _("Generating RSA keys with libgcrypt not implemented yet\n"));
return false;
}

31
src/gcrypt/rsagen.h Normal file
View file

@ -0,0 +1,31 @@
/*
rsagen.h -- RSA key generation and export
Copyright (C) 2008 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
$Id$
*/
#ifndef __TINC_RSAGEN_H__
#define __TINC_RSAGEN_H__
#include "rsa.h"
extern bool rsa_generate(rsa_t *rsa, size_t bits, unsigned long exponent);
extern bool rsa_write_pem_public_key(rsa_t *rsa, FILE *fp);
extern bool rsa_write_pem_private_key(rsa_t *rsa, FILE *fp);
#endif