cert.c revision 8f1316a0c677f211eaaa1346e21a03446b8c4fb1
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen/*
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen SSSD - certificate handling utils - openssl version
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen Copyright (C) Sumit Bose <sbose@redhat.com> 2015
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen This program is free software; you can redistribute it and/or modify
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen it under the terms of the GNU General Public License as published by
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen the Free Software Foundation; either version 3 of the License, or
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen (at your option) any later version.
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen This program is distributed in the hope that it will be useful,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen but WITHOUT ANY WARRANTY; without even the implied warranty of
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen GNU General Public License for more details.
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen You should have received a copy of the GNU General Public License
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen along with this program. If not, see <http://www.gnu.org/licenses/>.
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen*/
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <openssl/x509.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <openssl/bio.h>
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen#include <openssl/pem.h>
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "util/util.h"
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainenerrno_t sss_cert_der_to_pem(TALLOC_CTX *mem_ctx, const uint8_t *der_blob,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen size_t der_size, char **pem, size_t *pem_size)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen X509 *x509 = NULL;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen BIO *bio_mem = NULL;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen const unsigned char *d;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen int ret;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen long p_size;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen char *p;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (der_blob == NULL || der_size == 0) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return EINVAL;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen d = (const unsigned char *) der_blob;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen x509 = d2i_X509(NULL, &d, (int) der_size);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (x509 == NULL) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen DEBUG(SSSDBG_OP_FAILURE, "d2i_X509 failed.\n");
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return EINVAL;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen bio_mem = BIO_new(BIO_s_mem());
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (bio_mem == NULL) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen DEBUG(SSSDBG_OP_FAILURE, "BIO_new failed.\n");
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen ret = ENOMEM;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen goto done;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ret = PEM_write_bio_X509(bio_mem, x509);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (ret != 1) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen DEBUG(SSSDBG_OP_FAILURE, "PEM_write_bio_X509 failed.\n");
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen ret = EIO;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen goto done;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen p_size = BIO_get_mem_data(bio_mem, &p);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (p_size == 0) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen DEBUG(SSSDBG_OP_FAILURE, "Unexpected PEM size [%ld].\n", p_size);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ret = EINVAL;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen goto done;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (pem != NULL) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen *pem = talloc_strndup(mem_ctx, p, p_size);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (*pem == NULL) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen DEBUG(SSSDBG_OP_FAILURE, "talloc_memdup failed.\n");
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen ret = ENOMEM;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen goto done;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (pem_size != NULL) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen *pem_size = p_size;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen ret = EOK;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainendone:
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen X509_free(x509);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen BIO_free_all(bio_mem);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return ret;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainenerrno_t sss_cert_pem_to_der(TALLOC_CTX *mem_ctx, const char *pem,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen uint8_t **_der_blob, size_t *_der_size)
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen{
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen X509 *x509 = NULL;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen BIO *bio_mem = NULL;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen int ret;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen unsigned char *buf;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen int buf_size;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen uint8_t *der_blob;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen size_t der_size;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (pem == NULL) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen return EINVAL;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen bio_mem = BIO_new(BIO_s_mem());
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (bio_mem == NULL) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen DEBUG(SSSDBG_OP_FAILURE, "BIO_new failed.\n");
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen ret = ENOMEM;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen goto done;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen ret = BIO_puts(bio_mem, pem);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (ret <= 0) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen DEBUG(SSSDBG_OP_FAILURE, "BIO_puts failed.\n");
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ret = EIO;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen goto done;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen x509 = PEM_read_bio_X509(bio_mem, NULL, NULL, NULL);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (x509 == NULL) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen DEBUG(SSSDBG_OP_FAILURE, "PEM_read_bio_X509 failed.\n");
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen ret = EIO;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen goto done;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen buf_size = i2d_X509(x509, NULL);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen if (buf_size <= 0) {
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen DEBUG(SSSDBG_OP_FAILURE, "i2d_X509 failed.\n");
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen ret = EIO;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen goto done;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (_der_blob != NULL) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen buf = talloc_size(mem_ctx, buf_size);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (buf == NULL) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen DEBUG(SSSDBG_OP_FAILURE, "talloc_size failed.\n");
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ret = ENOMEM;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen goto done;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen der_blob = buf;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen der_size = i2d_X509(x509, &buf);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (der_size != buf_size) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen talloc_free(der_blob);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen "i2d_X509 size mismatch between two calls.\n");
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ret = EIO;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen goto done;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen *_der_blob = der_blob;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (_der_size != NULL) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen *_der_size = buf_size;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ret = EOK;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainendone:
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen X509_free(x509);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen BIO_free_all(bio_mem);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return ret;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen}
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen#define SSH_RSA_HEADER "ssh-rsa"
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen#define SSH_RSA_HEADER_LEN (sizeof(SSH_RSA_HEADER) - 1)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainenerrno_t cert_to_ssh_key(TALLOC_CTX *mem_ctx, const char *ca_db,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen const uint8_t *der_blob, size_t der_size,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen struct cert_verify_opts *cert_verify_opts,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen uint8_t **key, size_t *key_size)
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen{
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen int ret;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen size_t size;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen const unsigned char *d;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen uint8_t *buf = NULL;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen size_t c;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen X509 *cert = NULL;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen EVP_PKEY *cert_pub_key = NULL;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen const BIGNUM *n;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen const BIGNUM *e;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen int modulus_len;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen unsigned char modulus[OPENSSL_RSA_MAX_MODULUS_BITS/8];
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen int exponent_len;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen unsigned char exponent[OPENSSL_RSA_MAX_PUBEXP_BITS/8];
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (der_blob == NULL || der_size == 0) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return EINVAL;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen d = (const unsigned char *) der_blob;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen cert = d2i_X509(NULL, &d, (int) der_size);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (cert == NULL) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen DEBUG(SSSDBG_OP_FAILURE, "d2i_X509 failed.\n");
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen return EINVAL;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen /* TODO: verify certificate !!!!! */
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen cert_pub_key = X509_get_pubkey(cert);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (cert_pub_key == NULL) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen DEBUG(SSSDBG_OP_FAILURE, "X509_get_pubkey failed.\n");
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ret = EIO;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen goto done;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (EVP_PKEY_base_id(cert_pub_key) != EVP_PKEY_RSA) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen DEBUG(SSSDBG_CRIT_FAILURE,
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen "Expected RSA public key, found unsupported [%d].\n",
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen EVP_PKEY_base_id(cert_pub_key));
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ret = EINVAL;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen goto done;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen#if OPENSSL_VERSION_NUMBER >= 0x10100000L
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen RSA *rsa_pub_key = NULL;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen rsa_pub_key = EVP_PKEY_get0_RSA(cert_pub_key);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (rsa_pub_key == NULL) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ret = ENOMEM;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen goto done;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen RSA_get0_key(rsa_pub_key, &n, &e, NULL);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen#else
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen n = cert_pub_key->pkey.rsa->n;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen e = cert_pub_key->pkey.rsa->e;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen#endif
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen modulus_len = BN_bn2bin(n, modulus);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen exponent_len = BN_bn2bin(e, exponent);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen size = SSH_RSA_HEADER_LEN + 3 * sizeof(uint32_t)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen + modulus_len
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen + exponent_len
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen + 1; /* see comment about missing 00 below */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen buf = talloc_size(mem_ctx, size);
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (buf == NULL) {
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen DEBUG(SSSDBG_OP_FAILURE, "talloc_size failed.\n");
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen ret = ENOMEM;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen goto done;
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen c = 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen SAFEALIGN_SET_UINT32(buf, htobe32(SSH_RSA_HEADER_LEN), &c);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen safealign_memcpy(&buf[c], SSH_RSA_HEADER, SSH_RSA_HEADER_LEN, &c);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen SAFEALIGN_SET_UINT32(&buf[c], htobe32(exponent_len), &c);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen safealign_memcpy(&buf[c], exponent, exponent_len, &c);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen /* Adding missing 00 which afaik is added to make sure
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen * the bigint is handled as positive number */
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen /* TODO: make a better check if 00 must be added or not, e.g. ... & 0x80)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen */
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen SAFEALIGN_SET_UINT32(&buf[c], htobe32(modulus_len + 1), &c);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen SAFEALIGN_SETMEM_VALUE(&buf[c], '\0', unsigned char, &c);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen safealign_memcpy(&buf[c], modulus, modulus_len, &c);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen *key = buf;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen *key_size = size;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ret = EOK;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainendone:
704efd0b34e3611e3decf1d559fe6a93214b0bd0Timo Sirainen if (ret != EOK) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen talloc_free(buf);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen EVP_PKEY_free(cert_pub_key);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen X509_free(cert);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return ret;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen