示例#1
0
// Import a newly generated RSA1024 pvt key and a certificate
// to every slot and use the key to sign some data
static void test_import_and_sign_all_10_RSA() {

  EVP_PKEY    *evp;
  RSA         *rsak;
  X509        *cert;
  ASN1_TIME   *tm;
  CK_BYTE     i, j;
  CK_BYTE     some_data[32];
  CK_BYTE     e[] = {0x01, 0x00, 0x01};
  CK_BYTE     p[64];
  CK_BYTE     q[64];
  CK_BYTE     dp[64];
  CK_BYTE     dq[64];
  CK_BYTE     qinv[64];
  BIGNUM      *e_bn;
  CK_ULONG    class_k = CKO_PRIVATE_KEY;
  CK_ULONG    class_c = CKO_CERTIFICATE;
  CK_ULONG    kt = CKK_RSA;
  CK_BYTE     id = 0;
  CK_BYTE     sig[64];
  CK_ULONG    recv_len;
  CK_BYTE     value_c[3100];
  CK_ULONG    cert_len;
  CK_BYTE     der_encoded[80];
  CK_BYTE_PTR der_ptr;
  CK_BYTE_PTR r_ptr;
  CK_BYTE_PTR s_ptr;
  CK_ULONG    r_len;
  CK_ULONG    s_len;

  unsigned char  *px;

  CK_ATTRIBUTE privateKeyTemplate[] = {
    {CKA_CLASS, &class_k, sizeof(class_k)},
    {CKA_KEY_TYPE, &kt, sizeof(kt)},
    {CKA_ID, &id, sizeof(id)},
    {CKA_PUBLIC_EXPONENT, e, sizeof(e)},
    {CKA_PRIME_1, p, sizeof(p)},
    {CKA_PRIME_2, q, sizeof(q)},
    {CKA_EXPONENT_1, dp, sizeof(dp)},
    {CKA_EXPONENT_2, dq, sizeof(dq)},
    {CKA_COEFFICIENT, qinv, sizeof(qinv)}
  };

  CK_ATTRIBUTE publicKeyTemplate[] = {
    {CKA_CLASS, &class_c, sizeof(class_c)},
    {CKA_ID, &id, sizeof(id)},
    {CKA_VALUE, value_c, sizeof(value_c)}
  };

  CK_OBJECT_HANDLE obj[24];
  CK_SESSION_HANDLE session;
  CK_MECHANISM mech = {CKM_RSA_PKCS, NULL};

  evp = EVP_PKEY_new();

  if (evp == NULL)
    exit(EXIT_FAILURE);

  rsak = RSA_new();

  if (rsak == NULL)
    exit(EXIT_FAILURE);

  e_bn = BN_bin2bn(e, 3, NULL);

  if (e_bn == NULL)
    exit(EXIT_FAILURE);

  asrt(RSA_generate_key_ex(rsak, 1024, e_bn, NULL), 1, "GENERATE RSAK");

  asrt(BN_bn2bin(rsak->p, p), 64, "GET P");
  asrt(BN_bn2bin(rsak->q, q), 64, "GET Q");
  asrt(BN_bn2bin(rsak->dmp1, dp), 64, "GET DP");
  asrt(BN_bn2bin(rsak->dmq1, dp), 64, "GET DQ");
  asrt(BN_bn2bin(rsak->iqmp, qinv), 64, "GET QINV");



  if (EVP_PKEY_set1_RSA(evp, rsak) == 0)
    exit(EXIT_FAILURE);

  cert = X509_new();

  if (cert == NULL)
    exit(EXIT_FAILURE);

  if (X509_set_pubkey(cert, evp) == 0)
    exit(EXIT_FAILURE);

  tm = ASN1_TIME_new();
  if (tm == NULL)
    exit(EXIT_FAILURE);

  ASN1_TIME_set_string(tm, "000001010000Z");
  X509_set_notBefore(cert, tm);
  X509_set_notAfter(cert, tm);

  cert->sig_alg->algorithm = OBJ_nid2obj(8);
  cert->cert_info->signature->algorithm = OBJ_nid2obj(8);

  ASN1_BIT_STRING_set_bit(cert->signature, 8, 1);
  ASN1_BIT_STRING_set(cert->signature, "\x00", 1);

  px = value_c;
  if ((cert_len = (CK_ULONG) i2d_X509(cert, &px)) == 0 || cert_len > sizeof(value_c))
    exit(EXIT_FAILURE);

  publicKeyTemplate[2].ulValueLen = cert_len;

  asrt(funcs->C_Initialize(NULL), CKR_OK, "INITIALIZE");
  asrt(funcs->C_OpenSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &session), CKR_OK, "OpenSession1");
  asrt(funcs->C_Login(session, CKU_SO, "010203040506070801020304050607080102030405060708", 48), CKR_OK, "Login SO");

  for (i = 0; i < 24; i++) {
    id = i;
    asrt(funcs->C_CreateObject(session, publicKeyTemplate, 3, obj + i), CKR_OK, "IMPORT CERT");
    asrt(funcs->C_CreateObject(session, privateKeyTemplate, 9, obj + i), CKR_OK, "IMPORT KEY");
  }

  asrt(funcs->C_Logout(session), CKR_OK, "Logout SO");

  for (i = 0; i < 24; i++) {
    for (j = 0; j < 10; j++) {

      if(RAND_pseudo_bytes(some_data, sizeof(some_data)) == -1)
        exit(EXIT_FAILURE);

      asrt(funcs->C_Login(session, CKU_USER, "123456", 6), CKR_OK, "Login USER");
      asrt(funcs->C_SignInit(session, &mech, obj[i]), CKR_OK, "SignInit");

      recv_len = sizeof(sig);
      asrt(funcs->C_Sign(session, some_data, sizeof(some_data), sig, &recv_len), CKR_OK, "Sign");

      /* r_len = 32; */
      /* s_len = 32; */

      /* der_ptr = der_encoded; */
      /* *der_ptr++ = 0x30; */
      /* *der_ptr++ = 0xff; // placeholder, fix below */

      /* r_ptr = sig; */

      /* *der_ptr++ = 0x02; */
      /* *der_ptr++ = r_len; */
      /* if (*r_ptr >= 0x80) { */
      /*   *(der_ptr - 1) = *(der_ptr - 1) + 1; */
      /*   *der_ptr++ = 0x00; */
      /* } */
      /* else if (*r_ptr == 0x00 && *(r_ptr + 1) < 0x80) { */
      /*   r_len--; */
      /*   *(der_ptr - 1) = *(der_ptr - 1) - 1; */
      /*   r_ptr++; */
      /* } */
      /* memcpy(der_ptr, r_ptr, r_len); */
      /* der_ptr+= r_len; */

      /* s_ptr = sig + 32; */

      /* *der_ptr++ = 0x02; */
      /* *der_ptr++ = s_len; */
      /* if (*s_ptr >= 0x80) { */
      /*   *(der_ptr - 1) = *(der_ptr - 1) + 1; */
      /*   *der_ptr++ = 0x00; */
      /* } */
      /* else if (*s_ptr == 0x00 && *(s_ptr + 1) < 0x80) { */
      /*   s_len--; */
      /*   *(der_ptr - 1) = *(der_ptr - 1) - 1; */
      /*   s_ptr++; */
      /* } */
      /* memcpy(der_ptr, s_ptr, s_len); */
      /* der_ptr+= s_len; */

      /* der_encoded[1] = der_ptr - der_encoded - 2; */

      /* dump_hex(der_encoded, der_encoded[1] + 2, stderr, 1); */

      /* asrt(ECDSA_verify(0, some_data, sizeof(some_data), der_encoded, der_encoded[1] + 2, eck), 1, "ECDSA VERIFICATION"); */

      }
  }

  asrt(funcs->C_Logout(session), CKR_OK, "Logout USER");

  asrt(funcs->C_CloseSession(session), CKR_OK, "CloseSession");
  asrt(funcs->C_Finalize(NULL), CKR_OK, "FINALIZE");

}
示例#2
0
/*============================================================================
 * OpcUa_P_OpenSSL_X509_SelfSigned_Custom_Create
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_X509_SelfSigned_Custom_Create(
    OpcUa_CryptoProvider*       a_pProvider,
    OpcUa_Int32                 a_serialNumber,
    OpcUa_UInt32                a_validToInSec,
    OpcUa_Crypto_NameEntry*     a_pNameEntries,      /* will be used for issuer and subject thus it's selfigned cert */
    OpcUa_UInt                  a_nameEntriesCount,  /* will be used for issuer and subject thus it's selfigned cert */
    OpcUa_Key                   a_pSubjectPublicKey, /* EVP_PKEY* - type defines also public key algorithm */
    OpcUa_Crypto_Extension*     a_pExtensions,
    OpcUa_UInt                  a_extensionsCount,
    OpcUa_UInt                  a_signatureHashAlgorithm, /* EVP_sha1(),... */
    OpcUa_Key                   a_pIssuerPrivateKey, /* EVP_PKEY* - type defines also signature algorithm */
    OpcUa_ByteString*           a_pCertificate)
{
    OpcUa_UInt          i;

    X509_NAME*          pSubj               = OpcUa_Null;
    X509V3_CTX          ctx;
    const EVP_MD*       pDigest             = OpcUa_Null;

    X509*               pCert               = OpcUa_Null;
    EVP_PKEY*           pSubjectPublicKey   = OpcUa_Null;
    EVP_PKEY*           pIssuerPrivateKey   = OpcUa_Null;

    OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "X509_SelfSigned_Custom_Create");

    OpcUa_ReferenceParameter(a_pProvider);

    OpcUa_ReturnErrorIfArgumentNull(a_pNameEntries);
    OpcUa_ReturnErrorIfArgumentNull(a_pExtensions);
    OpcUa_ReturnErrorIfArgumentNull(a_pIssuerPrivateKey.Key.Data);
    OpcUa_ReturnErrorIfArgumentNull(a_pCertificate);

    if(a_pSubjectPublicKey.Type != OpcUa_Crypto_KeyType_Rsa_Public)
    {
        uStatus =  OpcUa_BadInvalidArgument;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(a_pIssuerPrivateKey.Type != OpcUa_Crypto_KeyType_Rsa_Private)
    {
        uStatus =  OpcUa_BadInvalidArgument;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    pSubjectPublicKey = d2i_PublicKey(EVP_PKEY_RSA,OpcUa_Null,((const unsigned char**)&(a_pSubjectPublicKey.Key.Data)),a_pSubjectPublicKey.Key.Length);
    if(pSubjectPublicKey == OpcUa_Null)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    pIssuerPrivateKey = d2i_PrivateKey(EVP_PKEY_RSA,OpcUa_Null,((const unsigned char**)&(a_pIssuerPrivateKey.Key.Data)),a_pIssuerPrivateKey.Key.Length);
    if(pIssuerPrivateKey == OpcUa_Null)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* create new certificate object */
    pCert = X509_new();
    if(pCert == OpcUa_Null)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* set version of certificate (V3 since internal representation starts versioning from 0) */
    if(X509_set_version(pCert, 2L) != 1)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* generate a unique number for a serial number if none provided. */
    if(a_serialNumber == 0)
    {
        ASN1_INTEGER* pSerialNumber = X509_get_serialNumber(pCert);

        pSerialNumber->type   = V_ASN1_INTEGER;
        pSerialNumber->data   = OPENSSL_realloc(pSerialNumber->data, 16);
        pSerialNumber->length = 16;

        if(pSerialNumber->data == NULL || OpcUa_P_Guid_Create((OpcUa_Guid*)pSerialNumber->data) == NULL)
        {
            uStatus =  OpcUa_Bad;
            OpcUa_GotoErrorIfBad(uStatus);
        }
    }

    /* use the integer passed in - note the API should not be using a 32-bit integer - must fix sometime */
    else if(ASN1_INTEGER_set(X509_get_serialNumber(pCert), a_serialNumber) == 0)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* add key to the request */
    if(X509_set_pubkey(pCert, pSubjectPublicKey) != 1)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(pSubjectPublicKey != OpcUa_Null)
    {
        EVP_PKEY_free(pSubjectPublicKey);
        pSubjectPublicKey = OpcUa_Null;
    }

    /* assign the subject name */
    pSubj = X509_NAME_new();
    if(!pSubj)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* create and add entries to subject name */
    for(i=0; i<a_nameEntriesCount; i++)
    {
        uStatus = OpcUa_P_OpenSSL_X509_Name_AddEntry(&pSubj, a_pNameEntries + i);
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* set subject name in request */
    if(X509_set_subject_name(pCert, pSubj) != 1)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* set name of issuer (CA) */
    if(X509_set_issuer_name(pCert, pSubj) != 1)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(!(X509_gmtime_adj(X509_get_notBefore(pCert), 0)))
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* set ending time of the certificate */
    if(!(X509_gmtime_adj(X509_get_notAfter(pCert), a_validToInSec)))
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* add x509v3 extensions */
    X509V3_set_ctx(&ctx, pCert, pCert, OpcUa_Null, OpcUa_Null, 0);

    for(i=0; i<a_extensionsCount; i++)
    {
        uStatus = OpcUa_P_OpenSSL_X509_AddCustomExtension(&pCert, a_pExtensions+i, &ctx);
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* sign certificate with the CA private key */
    switch(a_signatureHashAlgorithm)
    {
    case OPCUA_P_SHA_160:
        pDigest = EVP_sha1();
        break;
    case OPCUA_P_SHA_224:
        pDigest = EVP_sha224();
        break;
    case OPCUA_P_SHA_256:
        pDigest = EVP_sha256();
        break;
    case OPCUA_P_SHA_384:
        pDigest = EVP_sha384();
        break;
    case OPCUA_P_SHA_512:
        pDigest = EVP_sha512();
        break;
    default:
        uStatus =  OpcUa_BadNotSupported;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(!(X509_sign(pCert, pIssuerPrivateKey, pDigest)))
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(X509_verify(pCert, pIssuerPrivateKey) <= 0)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(pIssuerPrivateKey != OpcUa_Null)
    {
        EVP_PKEY_free(pIssuerPrivateKey);
        pIssuerPrivateKey = OpcUa_Null;
    }

    if(pSubj != OpcUa_Null)
    {
        X509_NAME_free(pSubj);
        pSubj = OpcUa_Null;
    }

    /* prepare container */
    memset(a_pCertificate, 0, sizeof(OpcUa_ByteString));

    /* get required length for conversion target buffer */
    a_pCertificate->Length = i2d_X509(pCert, NULL);

    if(a_pCertificate->Length <= 0)
    {
        /* conversion to DER not possible */
        uStatus = OpcUa_Bad;
    }

    /* allocate conversion target buffer */
    a_pCertificate->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pCertificate->Length);
    OpcUa_GotoErrorIfAllocFailed(a_pCertificate->Data);

    /* convert into DER */
    a_pCertificate->Length = i2d_X509(pCert, &(a_pCertificate->Data));
    if(a_pCertificate->Length <= 0)
    {
        /* conversion to DER not possible */
        uStatus = OpcUa_Bad;
    }
    else
    {
        /* correct pointer incrementation by i2d_X509() */
        a_pCertificate->Data -= a_pCertificate->Length;
    }

    X509_free(pCert);

OpcUa_ReturnStatusCode;

OpcUa_BeginErrorHandling;

    X509_free(pCert);

    if(pSubjectPublicKey != OpcUa_Null)
    {
        EVP_PKEY_free(pSubjectPublicKey);
    }

    if(pIssuerPrivateKey != OpcUa_Null)
    {
        EVP_PKEY_free(pIssuerPrivateKey);
    }

    if(pSubj != OpcUa_Null)
    {
        X509_NAME_free(pSubj);
    }

OpcUa_FinishErrorHandling;
}
示例#3
0
extern "C" int32_t EncodeX509(X509* x, uint8_t* buf)
{
    return i2d_X509(x, &buf);
}
示例#4
0
ssize_t mailstream_ssl_get_certificate(mailstream *stream, unsigned char **cert_DER)
{
#ifdef USE_SSL
    struct mailstream_ssl_data *data = NULL;
    ssize_t len = 0;
#ifndef USE_GNUTLS
    SSL *ssl_conn = NULL;
    X509 *cert = NULL;
#else
    gnutls_session session = NULL;
    const gnutls_datum *raw_cert_list;
    unsigned int raw_cert_list_length;
    gnutls_x509_crt cert = NULL;
    size_t cert_size;
#endif

    if (cert_DER == NULL || stream == NULL || stream->low == NULL)
        return -1;

    data = stream->low->data;
    if (data == NULL)
        return -1;

#ifndef USE_GNUTLS
    ssl_conn = data->ssl_conn;
    if (ssl_conn == NULL)
        return -1;

    cert = SSL_get_peer_certificate(ssl_conn);
    if (cert == NULL)
        return -1;

    len = i2d_X509(cert, NULL);
    * cert_DER = malloc(len);
    if (* cert_DER == NULL)
        return -1;

    i2d_X509(cert, cert_DER);

    X509_free(cert);

    return len;
#else
    session = data->session;
    raw_cert_list = gnutls_certificate_get_peers(session, &raw_cert_list_length);

    if (raw_cert_list
            && gnutls_certificate_type_get(session) == GNUTLS_CRT_X509
            &&  gnutls_x509_crt_init(&cert) >= 0
            &&  gnutls_x509_crt_import(cert, &raw_cert_list[0], GNUTLS_X509_FMT_DER) >= 0) {
        cert_size = 0;
        if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, NULL, &cert_size)
                != GNUTLS_E_SHORT_MEMORY_BUFFER)
            return -1;

        *cert_DER = malloc (cert_size);
        if (*cert_DER == NULL)
            return -1;

        if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, *cert_DER, &cert_size) < 0)
            return -1;

        len = (ssize_t)cert_size;
        gnutls_x509_crt_deinit(cert);

        return len;
    }
#endif
#endif
    return -1;
}
示例#5
0
文件: tls_drv.c 项目: adkron/ejabberd
static int tls_drv_control(ErlDrvData handle,
			   unsigned int command,
			   char *buf, int len,
			   char **rbuf, int rlen)
{
   tls_data *d = (tls_data *)handle;
   int res;
   int size;
   ErlDrvBinary *b;
   X509 *cert;
   unsigned int flags = command;

   command &= 0xffff;

   ERR_clear_error();
   switch (command)
   {
      case SET_CERTIFICATE_FILE_ACCEPT:
      case SET_CERTIFICATE_FILE_CONNECT: {
	 time_t mtime = 0;
	 SSL_CTX *ssl_ctx = hash_table_lookup(buf, &mtime);
	 if (is_key_file_modified(buf, &mtime) || ssl_ctx == NULL)
	 {
	    SSL_CTX *ctx;

	    hash_table_insert(buf, mtime, NULL);

	    ctx = SSL_CTX_new(SSLv23_method());
	    die_unless(ctx, "SSL_CTX_new failed");

	    res = SSL_CTX_use_certificate_chain_file(ctx, buf);
	    die_unless(res > 0, "SSL_CTX_use_certificate_file failed");

	    res = SSL_CTX_use_PrivateKey_file(ctx, buf, SSL_FILETYPE_PEM);
	    die_unless(res > 0, "SSL_CTX_use_PrivateKey_file failed");

	    res = SSL_CTX_check_private_key(ctx);
	    die_unless(res > 0, "SSL_CTX_check_private_key failed");

	    SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
	    SSL_CTX_set_default_verify_paths(ctx);
#ifdef SSL_MODE_RELEASE_BUFFERS
	    SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
	    /* SSL_CTX_load_verify_locations(ctx, "/etc/ejabberd/ca_certificates.pem", NULL); */
	    /* SSL_CTX_load_verify_locations(ctx, NULL, "/etc/ejabberd/ca_certs/"); */

	    /* This IF is commented to allow verification in all cases: */
	    /* if (command == SET_CERTIFICATE_FILE_ACCEPT) */
	    /* { */
	       SSL_CTX_set_verify(ctx,
				  SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
				  verify_callback);
	    /* } */

	    ssl_ctx = ctx;
	    hash_table_insert(buf, mtime, ssl_ctx);
	 }

	 d->ssl = SSL_new(ssl_ctx);
	 die_unless(d->ssl, "SSL_new failed");

	 if (flags & VERIFY_NONE)
	    SSL_set_verify(d->ssl, SSL_VERIFY_NONE, verify_callback);

	 d->bio_read = BIO_new(BIO_s_mem());
	 d->bio_write = BIO_new(BIO_s_mem());

	 SSL_set_bio(d->ssl, d->bio_read, d->bio_write);

	 if (command == SET_CERTIFICATE_FILE_ACCEPT) {
	    SSL_set_options(d->ssl, SSL_OP_NO_TICKET);
	    SSL_set_accept_state(d->ssl);
	 } else {
	    SSL_set_options(d->ssl, SSL_OP_NO_SSLv2|SSL_OP_NO_TICKET);
	    SSL_set_connect_state(d->ssl);
	 }
	 break;
      }
      case SET_ENCRYPTED_INPUT:
	 die_unless(d->ssl, "SSL not initialized");
	 BIO_write(d->bio_read, buf, len);
	 break;
      case SET_DECRYPTED_OUTPUT:
	 die_unless(d->ssl, "SSL not initialized");
	 res = SSL_write(d->ssl, buf, len);
	 if (res <= 0) 
	 {
	    res = SSL_get_error(d->ssl, res);
	    if (res == SSL_ERROR_WANT_READ || res == SSL_ERROR_WANT_WRITE) 
	    {
	       b = driver_alloc_binary(1);
	       b->orig_bytes[0] = 2;
	       *rbuf = (char *)b;
	       return 1;
	    } else {
	       die_unless(0, "SSL_write failed");
	    }
	 }
	 break;
      case GET_ENCRYPTED_OUTPUT:
	 die_unless(d->ssl, "SSL not initialized");
	 size = BIO_ctrl_pending(d->bio_write) + 1;
	 b = driver_alloc_binary(size);
	 b->orig_bytes[0] = 0;
	 BIO_read(d->bio_write, b->orig_bytes + 1, size - 1);
	 *rbuf = (char *)b;
	 return size;
      case GET_DECRYPTED_INPUT:
	 if (!SSL_is_init_finished(d->ssl))
	 {
	    res = SSL_do_handshake(d->ssl);
	    if (res <= 0)
	       die_unless(SSL_get_error(d->ssl, res) == SSL_ERROR_WANT_READ,
			  "SSL_do_handshake failed");
	 } else {
	    size = BUF_SIZE + 1;
	    rlen = 1;
	    b = driver_alloc_binary(size);
	    b->orig_bytes[0] = 0;

	    while ((res = SSL_read(d->ssl,
				   b->orig_bytes + rlen, BUF_SIZE)) > 0)
	    {
	       //printf("%d bytes of decrypted data read from state machine\r\n",res);
	       rlen += res;
	       size += BUF_SIZE;
	       b = driver_realloc_binary(b, size);
	    }

	    if (res < 0)
	    {
	       int err = SSL_get_error(d->ssl, res);

	       if (err == SSL_ERROR_WANT_READ)
	       {
		  //printf("SSL_read wants more data\r\n");
		  //return 0;
	       }
	       // TODO
	    }
	    b = driver_realloc_binary(b, rlen);
	    *rbuf = (char *)b;
	    return rlen;
	 }
	 break;
      case GET_PEER_CERTIFICATE:
	 cert = SSL_get_peer_certificate(d->ssl);
	 if (cert == NULL)
	 {
	    b = driver_alloc_binary(1);
	    b->orig_bytes[0] = 1;
	    *rbuf = (char *)b;
	    return 1;
	 } else {
	    unsigned char *tmp_buf;
	    rlen = i2d_X509(cert, NULL);
	    if (rlen >= 0)
	    {
	       rlen++;
	       b = driver_alloc_binary(rlen);
	       b->orig_bytes[0] = 0;
	       tmp_buf = (unsigned char *)&b->orig_bytes[1];
	       i2d_X509(cert, &tmp_buf);
	       X509_free(cert);
	       *rbuf = (char *)b;
	       return rlen;
	    } else
	       X509_free(cert);
	 }
	 break;
      case GET_VERIFY_RESULT:
	 b = driver_alloc_binary(1);
	 b->orig_bytes[0] = SSL_get_verify_result(d->ssl);
	 *rbuf = (char *)b;
	 return 1;
	 break;
   }

   b = driver_alloc_binary(1);
   b->orig_bytes[0] = 0;
   *rbuf = (char *)b;
   return 1;
}
int x509_main(int argc, char **argv)
{
    ASN1_INTEGER *sno = NULL;
    ASN1_OBJECT *objtmp = NULL;
    BIO *out = NULL;
    CONF *extconf = NULL;
    EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL;
    STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
    STACK_OF(OPENSSL_STRING) *sigopts = NULL;
    X509 *x = NULL, *xca = NULL;
    X509_REQ *req = NULL, *rq = NULL;
    X509_STORE *ctx = NULL;
    const EVP_MD *digest = NULL;
    char *CAkeyfile = NULL, *CAserial = NULL, *fkeyfile = NULL, *alias = NULL;
    char *checkhost = NULL, *checkemail = NULL, *checkip = NULL;
    char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL;
    char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL;
    char buf[256], *prog;
    int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0, pprint = 0;
    int C = 0, CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM;
    int fingerprint = 0, reqfile = 0, need_rand = 0, checkend = 0;
    int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM;
    int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0;
    int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0;
    int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0;
    int ret = 1, i, num = 0, badsig = 0, clrext = 0, nocert = 0;
    int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0;
    int enddate = 0;
    time_t checkoffset = 0;
    unsigned long nmflag = 0, certflag = 0;
    char nmflag_set = 0;
    OPTION_CHOICE o;
    ENGINE *e = NULL;
#ifndef OPENSSL_NO_MD5
    int subject_hash_old = 0, issuer_hash_old = 0;
#endif

    ctx = X509_STORE_new();
    if (ctx == NULL)
        goto end;
    X509_STORE_set_verify_cb(ctx, callb);

    prog = opt_init(argc, argv, x509_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(x509_options);
            ret = 0;
            goto end;
        case OPT_INFORM:
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat))
                goto opthelp;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUTFORM:
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat))
                goto opthelp;
            break;
        case OPT_KEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat))
                goto opthelp;
            break;
        case OPT_CAFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAformat))
                goto opthelp;
            break;
        case OPT_CAKEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAkeyformat))
                goto opthelp;
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_REQ:
            reqfile = need_rand = 1;
            break;

        case OPT_SIGOPT:
            if (!sigopts)
                sigopts = sk_OPENSSL_STRING_new_null();
            if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
                goto opthelp;
            break;
        case OPT_DAYS:
            days = atoi(opt_arg());
            break;
        case OPT_PASSIN:
            passinarg = opt_arg();
            break;
        case OPT_EXTFILE:
            extfile = opt_arg();
            break;
        case OPT_EXTENSIONS:
            extsect = opt_arg();
            break;
        case OPT_SIGNKEY:
            keyfile = opt_arg();
            sign_flag = ++num;
            need_rand = 1;
            break;
        case OPT_CA:
            CAfile = opt_arg();
            CA_flag = ++num;
            need_rand = 1;
            break;
        case OPT_CAKEY:
            CAkeyfile = opt_arg();
            break;
        case OPT_CASERIAL:
            CAserial = opt_arg();
            break;
        case OPT_SET_SERIAL:
            if (sno != NULL) {
                BIO_printf(bio_err, "Serial number supplied twice\n");
                goto opthelp;
            }
            if ((sno = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL)
                goto opthelp;
            break;
        case OPT_FORCE_PUBKEY:
            fkeyfile = opt_arg();
            break;
        case OPT_ADDTRUST:
            if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
                BIO_printf(bio_err,
                           "%s: Invalid trust object value %s\n",
                           prog, opt_arg());
                goto opthelp;
            }
            if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL)
                goto end;
            sk_ASN1_OBJECT_push(trust, objtmp);
            objtmp = NULL;
            trustout = 1;
            break;
        case OPT_ADDREJECT:
            if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
                BIO_printf(bio_err,
                           "%s: Invalid reject object value %s\n",
                           prog, opt_arg());
                goto opthelp;
            }
            if (reject == NULL
                && (reject = sk_ASN1_OBJECT_new_null()) == NULL)
                goto end;
            sk_ASN1_OBJECT_push(reject, objtmp);
            objtmp = NULL;
            trustout = 1;
            break;
        case OPT_SETALIAS:
            alias = opt_arg();
            trustout = 1;
            break;
        case OPT_CERTOPT:
            if (!set_cert_ex(&certflag, opt_arg()))
                goto opthelp;
            break;
        case OPT_NAMEOPT:
            nmflag_set = 1;
            if (!set_name_ex(&nmflag, opt_arg()))
                goto opthelp;
            break;
        case OPT_ENGINE:
            e = setup_engine(opt_arg(), 0);
            break;
        case OPT_C:
            C = ++num;
            break;
        case OPT_EMAIL:
            email = ++num;
            break;
        case OPT_OCSP_URI:
            ocsp_uri = ++num;
            break;
        case OPT_SERIAL:
            serial = ++num;
            break;
        case OPT_NEXT_SERIAL:
            next_serial = ++num;
            break;
        case OPT_MODULUS:
            modulus = ++num;
            break;
        case OPT_PUBKEY:
            pubkey = ++num;
            break;
        case OPT_X509TOREQ:
            x509req = ++num;
            break;
        case OPT_TEXT:
            text = ++num;
            break;
        case OPT_SUBJECT:
            subject = ++num;
            break;
        case OPT_ISSUER:
            issuer = ++num;
            break;
        case OPT_FINGERPRINT:
            fingerprint = ++num;
            break;
        case OPT_HASH:
            subject_hash = ++num;
            break;
        case OPT_ISSUER_HASH:
            issuer_hash = ++num;
            break;
        case OPT_PURPOSE:
            pprint = ++num;
            break;
        case OPT_STARTDATE:
            startdate = ++num;
            break;
        case OPT_ENDDATE:
            enddate = ++num;
            break;
        case OPT_NOOUT:
            noout = ++num;
            break;
        case OPT_NOCERT:
            nocert = 1;
            break;
        case OPT_TRUSTOUT:
            trustout = 1;
            break;
        case OPT_CLRTRUST:
            clrtrust = ++num;
            break;
        case OPT_CLRREJECT:
            clrreject = ++num;
            break;
        case OPT_ALIAS:
            aliasout = ++num;
            break;
        case OPT_CACREATESERIAL:
            CA_createserial = ++num;
            break;
        case OPT_CLREXT:
            clrext = 1;
            break;
        case OPT_OCSPID:
            ocspid = ++num;
            break;
        case OPT_BADSIG:
            badsig = 1;
            break;
#ifndef OPENSSL_NO_MD5
        case OPT_SUBJECT_HASH_OLD:
            subject_hash_old = ++num;
            break;
        case OPT_ISSUER_HASH_OLD:
            issuer_hash_old = ++num;
            break;
#else
        case OPT_SUBJECT_HASH_OLD:
        case OPT_ISSUER_HASH_OLD:
            break;
#endif
        case OPT_DATES:
            startdate = ++num;
            enddate = ++num;
            break;
        case OPT_CHECKEND:
            checkend = 1;
            {
                intmax_t temp = 0;
                if (!opt_imax(opt_arg(), &temp))
                    goto opthelp;
                checkoffset = (time_t)temp;
                if ((intmax_t)checkoffset != temp) {
                    BIO_printf(bio_err, "%s: checkend time out of range %s\n",
                               prog, opt_arg());
                    goto opthelp;
                }
            }
            break;
        case OPT_CHECKHOST:
            checkhost = opt_arg();
            break;
        case OPT_CHECKEMAIL:
            checkemail = opt_arg();
            break;
        case OPT_CHECKIP:
            checkip = opt_arg();
            break;
        case OPT_MD:
            if (!opt_md(opt_unknown(), &digest))
                goto opthelp;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();
    if (argc != 0) {
        BIO_printf(bio_err, "%s: Unknown parameter %s\n", prog, argv[0]);
        goto opthelp;
    }

    if (!nmflag_set)
        nmflag = XN_FLAG_ONELINE;

    out = bio_open_default(outfile, 'w', outformat);
    if (out == NULL)
        goto end;

    if (need_rand)
        app_RAND_load_file(NULL, 0);

    if (!app_passwd(passinarg, NULL, &passin, NULL)) {
        BIO_printf(bio_err, "Error getting password\n");
        goto end;
    }

    if (!X509_STORE_set_default_paths(ctx)) {
        ERR_print_errors(bio_err);
        goto end;
    }

    if (fkeyfile) {
        fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "Forced key");
        if (fkey == NULL)
            goto end;
    }

    if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) {
        CAkeyfile = CAfile;
    } else if ((CA_flag) && (CAkeyfile == NULL)) {
        BIO_printf(bio_err,
                   "need to specify a CAkey if using the CA command\n");
        goto end;
    }

    if (extfile) {
        X509V3_CTX ctx2;
        if ((extconf = app_load_config(extfile)) == NULL)
            goto end;
        if (!extsect) {
            extsect = NCONF_get_string(extconf, "default", "extensions");
            if (!extsect) {
                ERR_clear_error();
                extsect = "default";
            }
        }
        X509V3_set_ctx_test(&ctx2);
        X509V3_set_nconf(&ctx2, extconf);
        if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) {
            BIO_printf(bio_err,
                       "Error Loading extension section %s\n", extsect);
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (reqfile) {
        EVP_PKEY *pkey;
        BIO *in;

        if (!sign_flag && !CA_flag) {
            BIO_printf(bio_err, "We need a private key to sign with\n");
            goto end;
        }
        in = bio_open_default(infile, 'r', informat);
        if (in == NULL)
            goto end;
        req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
        BIO_free(in);

        if (req == NULL) {
            ERR_print_errors(bio_err);
            goto end;
        }

        if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) {
            BIO_printf(bio_err, "error unpacking public key\n");
            goto end;
        }
        i = X509_REQ_verify(req, pkey);
        if (i < 0) {
            BIO_printf(bio_err, "Signature verification error\n");
            ERR_print_errors(bio_err);
            goto end;
        }
        if (i == 0) {
            BIO_printf(bio_err,
                       "Signature did not match the certificate request\n");
            goto end;
        } else
            BIO_printf(bio_err, "Signature ok\n");

        print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
                   nmflag);

        if ((x = X509_new()) == NULL)
            goto end;

        if (sno == NULL) {
            sno = ASN1_INTEGER_new();
            if (sno == NULL || !rand_serial(NULL, sno))
                goto end;
            if (!X509_set_serialNumber(x, sno))
                goto end;
            ASN1_INTEGER_free(sno);
            sno = NULL;
        } else if (!X509_set_serialNumber(x, sno))
            goto end;

        if (!X509_set_issuer_name(x, X509_REQ_get_subject_name(req)))
            goto end;
        if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req)))
            goto end;
        if (!set_cert_times(x, NULL, NULL, days))
            goto end;

        if (fkey)
            X509_set_pubkey(x, fkey);
        else {
            pkey = X509_REQ_get0_pubkey(req);
            X509_set_pubkey(x, pkey);
        }
    } else
        x = load_cert(infile, informat, "Certificate");

    if (x == NULL)
        goto end;
    if (CA_flag) {
        xca = load_cert(CAfile, CAformat, "CA Certificate");
        if (xca == NULL)
            goto end;
    }

    if (!noout || text || next_serial) {
        OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3");

    }

    if (alias)
        X509_alias_set1(x, (unsigned char *)alias, -1);

    if (clrtrust)
        X509_trust_clear(x);
    if (clrreject)
        X509_reject_clear(x);

    if (trust) {
        for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) {
            objtmp = sk_ASN1_OBJECT_value(trust, i);
            X509_add1_trust_object(x, objtmp);
        }
        objtmp = NULL;
    }

    if (reject) {
        for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) {
            objtmp = sk_ASN1_OBJECT_value(reject, i);
            X509_add1_reject_object(x, objtmp);
        }
        objtmp = NULL;
    }

    if (badsig) {
        const ASN1_BIT_STRING *signature;

        X509_get0_signature(&signature, NULL, x);
        corrupt_signature(signature);
    }

    if (num) {
        for (i = 1; i <= num; i++) {
            if (issuer == i) {
                print_name(out, "issuer=", X509_get_issuer_name(x), nmflag);
            } else if (subject == i) {
                print_name(out, "subject=",
                           X509_get_subject_name(x), nmflag);
            } else if (serial == i) {
                BIO_printf(out, "serial=");
                i2a_ASN1_INTEGER(out, X509_get_serialNumber(x));
                BIO_printf(out, "\n");
            } else if (next_serial == i) {
                ASN1_INTEGER *ser = X509_get_serialNumber(x);
                BIGNUM *bnser = ASN1_INTEGER_to_BN(ser, NULL);

                if (!bnser)
                    goto end;
                if (!BN_add_word(bnser, 1))
                    goto end;
                ser = BN_to_ASN1_INTEGER(bnser, NULL);
                if (!ser)
                    goto end;
                BN_free(bnser);
                i2a_ASN1_INTEGER(out, ser);
                ASN1_INTEGER_free(ser);
                BIO_puts(out, "\n");
            } else if ((email == i) || (ocsp_uri == i)) {
                int j;
                STACK_OF(OPENSSL_STRING) *emlst;
                if (email == i)
                    emlst = X509_get1_email(x);
                else
                    emlst = X509_get1_ocsp(x);
                for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
                    BIO_printf(out, "%s\n",
                               sk_OPENSSL_STRING_value(emlst, j));
                X509_email_free(emlst);
            } else if (aliasout == i) {
                unsigned char *alstr;
                alstr = X509_alias_get0(x, NULL);
                if (alstr)
                    BIO_printf(out, "%s\n", alstr);
                else
                    BIO_puts(out, "<No Alias>\n");
            } else if (subject_hash == i) {
                BIO_printf(out, "%08lx\n", X509_subject_name_hash(x));
            }
#ifndef OPENSSL_NO_MD5
            else if (subject_hash_old == i) {
                BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x));
            }
#endif
            else if (issuer_hash == i) {
                BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x));
            }
#ifndef OPENSSL_NO_MD5
            else if (issuer_hash_old == i) {
                BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x));
            }
#endif
            else if (pprint == i) {
                X509_PURPOSE *ptmp;
                int j;
                BIO_printf(out, "Certificate purposes:\n");
                for (j = 0; j < X509_PURPOSE_get_count(); j++) {
                    ptmp = X509_PURPOSE_get0(j);
                    purpose_print(out, x, ptmp);
                }
            } else if (modulus == i) {
                EVP_PKEY *pkey;

                pkey = X509_get0_pubkey(x);
                if (pkey == NULL) {
                    BIO_printf(bio_err, "Modulus=unavailable\n");
                    ERR_print_errors(bio_err);
                    goto end;
                }
                BIO_printf(out, "Modulus=");
#ifndef OPENSSL_NO_RSA
                if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
                    const BIGNUM *n;
                    RSA_get0_key(EVP_PKEY_get0_RSA(pkey), &n, NULL, NULL);
                    BN_print(out, n);
                } else
#endif
#ifndef OPENSSL_NO_DSA
                if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) {
                    const BIGNUM *dsapub = NULL;
                    DSA_get0_key(EVP_PKEY_get0_DSA(pkey), &dsapub, NULL);
                    BN_print(out, dsapub);
                } else
#endif
                {
                    BIO_printf(out, "Wrong Algorithm type");
                }
                BIO_printf(out, "\n");
            } else if (pubkey == i) {
                EVP_PKEY *pkey;

                pkey = X509_get0_pubkey(x);
                if (pkey == NULL) {
                    BIO_printf(bio_err, "Error getting public key\n");
                    ERR_print_errors(bio_err);
                    goto end;
                }
                PEM_write_bio_PUBKEY(out, pkey);
            } else if (C == i) {
                unsigned char *d;
                char *m;
                int len;

                X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof buf);
                BIO_printf(out, "/*\n"
                                " * Subject: %s\n", buf);

                X509_NAME_oneline(X509_get_issuer_name(x), buf, sizeof buf);
                BIO_printf(out, " * Issuer:  %s\n"
                                " */\n", buf);

                len = i2d_X509(x, NULL);
                m = app_malloc(len, "x509 name buffer");
                d = (unsigned char *)m;
                len = i2d_X509_NAME(X509_get_subject_name(x), &d);
                print_array(out, "the_subject_name", len, (unsigned char *)m);
                d = (unsigned char *)m;
                len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
                print_array(out, "the_public_key", len, (unsigned char *)m);
                d = (unsigned char *)m;
                len = i2d_X509(x, &d);
                print_array(out, "the_certificate", len, (unsigned char *)m);
                OPENSSL_free(m);
            } else if (text == i) {
                X509_print_ex(out, x, nmflag, certflag);
            } else if (startdate == i) {
                BIO_puts(out, "notBefore=");
                ASN1_TIME_print(out, X509_get0_notBefore(x));
                BIO_puts(out, "\n");
            } else if (enddate == i) {
                BIO_puts(out, "notAfter=");
                ASN1_TIME_print(out, X509_get0_notAfter(x));
                BIO_puts(out, "\n");
            } else if (fingerprint == i) {
                int j;
                unsigned int n;
                unsigned char md[EVP_MAX_MD_SIZE];
                const EVP_MD *fdig = digest;

                if (!fdig)
                    fdig = EVP_sha1();

                if (!X509_digest(x, fdig, md, &n)) {
                    BIO_printf(bio_err, "out of memory\n");
                    goto end;
                }
                BIO_printf(out, "%s Fingerprint=",
                           OBJ_nid2sn(EVP_MD_type(fdig)));
                for (j = 0; j < (int)n; j++) {
                    BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n)
                               ? '\n' : ':');
                }
            }

            /* should be in the library */
            else if ((sign_flag == i) && (x509req == 0)) {
                BIO_printf(bio_err, "Getting Private key\n");
                if (Upkey == NULL) {
                    Upkey = load_key(keyfile, keyformat, 0,
                                     passin, e, "Private key");
                    if (Upkey == NULL)
                        goto end;
                }

                assert(need_rand);
                if (!sign(x, Upkey, days, clrext, digest, extconf, extsect))
                    goto end;
            } else if (CA_flag == i) {
                BIO_printf(bio_err, "Getting CA Private Key\n");
                if (CAkeyfile != NULL) {
                    CApkey = load_key(CAkeyfile, CAkeyformat,
                                      0, passin, e, "CA Private Key");
                    if (CApkey == NULL)
                        goto end;
                }

                assert(need_rand);
                if (!x509_certify(ctx, CAfile, digest, x, xca,
                                  CApkey, sigopts,
                                  CAserial, CA_createserial, days, clrext,
                                  extconf, extsect, sno, reqfile))
                    goto end;
            } else if (x509req == i) {
                EVP_PKEY *pk;

                BIO_printf(bio_err, "Getting request Private Key\n");
                if (keyfile == NULL) {
                    BIO_printf(bio_err, "no request key file specified\n");
                    goto end;
                } else {
                    pk = load_key(keyfile, keyformat, 0,
                                  passin, e, "request key");
                    if (pk == NULL)
                        goto end;
                }

                BIO_printf(bio_err, "Generating certificate request\n");

                rq = X509_to_X509_REQ(x, pk, digest);
                EVP_PKEY_free(pk);
                if (rq == NULL) {
                    ERR_print_errors(bio_err);
                    goto end;
                }
                if (!noout) {
                    X509_REQ_print(out, rq);
                    PEM_write_bio_X509_REQ(out, rq);
                }
                noout = 1;
            } else if (ocspid == i) {
                X509_ocspid_print(out, x);
            }
        }
    }

    if (checkend) {
        time_t tcheck = time(NULL) + checkoffset;

        if (X509_cmp_time(X509_get0_notAfter(x), &tcheck) < 0) {
            BIO_printf(out, "Certificate will expire\n");
            ret = 1;
        } else {
            BIO_printf(out, "Certificate will not expire\n");
            ret = 0;
        }
        goto end;
    }

    print_cert_checks(out, x, checkhost, checkemail, checkip);

    if (noout || nocert) {
        ret = 0;
        goto end;
    }

    if (outformat == FORMAT_ASN1)
        i = i2d_X509_bio(out, x);
    else if (outformat == FORMAT_PEM) {
        if (trustout)
            i = PEM_write_bio_X509_AUX(out, x);
        else
            i = PEM_write_bio_X509(out, x);
    } else {
        BIO_printf(bio_err, "bad output format specified for outfile\n");
        goto end;
    }
    if (!i) {
        BIO_printf(bio_err, "unable to write certificate\n");
        ERR_print_errors(bio_err);
        goto end;
    }
    ret = 0;
 end:
    if (need_rand)
        app_RAND_write_file(NULL);
    NCONF_free(extconf);
    BIO_free_all(out);
    X509_STORE_free(ctx);
    X509_REQ_free(req);
    X509_free(x);
    X509_free(xca);
    EVP_PKEY_free(Upkey);
    EVP_PKEY_free(CApkey);
    EVP_PKEY_free(fkey);
    sk_OPENSSL_STRING_free(sigopts);
    X509_REQ_free(rq);
    ASN1_INTEGER_free(sno);
    sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
    sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
    ASN1_OBJECT_free(objtmp);
    release_engine(e);
    OPENSSL_free(passin);
    return (ret);
}
示例#7
0
extern "C" int32_t CryptoNative_GetX509DerSize(X509* x)
{
    return i2d_X509(x, nullptr);
}
示例#8
0
int CryptoAPI_verify_certificate(X509 *x509)
{
  int ret = -1;
  int len;
  unsigned char *buf = NULL;

  PCCERT_CONTEXT pCertContext = NULL;
  PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  CERT_ENHKEY_USAGE EnhkeyUsage;
  CERT_USAGE_MATCH CertUsage;  
  CERT_CHAIN_PARA ChainPara;

  /* Convert from internal X509 format to DER */
  len = i2d_X509(x509, &buf);
  if (len < 0) {
	SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_ASN1_LIB);
	goto err;
  }

#ifdef __MINGW32_VERSION
    /* MinGW w32api is incomplete when it comes to CryptoAPI, as per version 3.1
     * anyway. This is a hack around that problem. */
    if (crypt32dll == NULL) {
	crypt32dll = LoadLibrary("crypt32");
	if (crypt32dll == NULL) {
	    CRYPTOAPIerr(CRYPTOAPI_F_LOAD_LIBRARY);
	    goto err;
	}
    }
    if (CertCreateCertificateContext == NULL) {
	CertCreateCertificateContext = GetProcAddress(crypt32dll,
		"CertCreateCertificateContext");
	if (CertCreateCertificateContext == NULL) {
	    CRYPTOAPIerr(CRYPTOAPI_F_GET_PROC_ADDRESS);
	    goto err;
	}
    }
#endif

  /* Create a certificate context based on the above certificate */
  pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  	buf, len);
  if (pCertContext == NULL) {
	CRYPTOAPIerr(CRYPTOAPI_F_CERT_CREATE_CERT_CONTEXT);
	goto err;
  }

  /* Create an empty issuer list */
  EnhkeyUsage.cUsageIdentifier = 0;
  EnhkeyUsage.rgpszUsageIdentifier = NULL;
  CertUsage.dwType = USAGE_MATCH_TYPE_AND;
  CertUsage.Usage  = EnhkeyUsage;

  /* Searching and matching criteria to be used when building the chain */
  ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
  ChainPara.RequestedUsage = CertUsage;

  /* Get the certificate chain of our certificate */
  if (!CertGetCertificateChain(NULL, pCertContext, NULL, NULL, &ChainPara,
	0, NULL, &pChainContext)) {
	CRYPTOAPIerr(CRYPTOAPI_F_CERT_GET_CERT_CHAIN);
	goto err;
  }

  /* return 1 when the certificate is trusted, 0 when it's not; -1 on error */
  ret = (pChainContext->TrustStatus.dwErrorStatus == CERT_TRUST_NO_ERROR);

  err:
    if (buf)
	OPENSSL_free(buf);
    if (pChainContext)
	CertFreeCertificateChain(pChainContext);
    if (pCertContext)
	CertFreeCertificateContext(pCertContext);

  return ret;
}
示例#9
0
int
sc_pkcs15_prkey_attrs_from_cert(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *cert_object,
		struct sc_pkcs15_object **out_key_object)
{
	struct sc_context *ctx = p15card->card->ctx;
#ifdef ENABLE_OPENSSL
	struct sc_pkcs15_object *key_object = NULL;
	struct sc_pkcs15_prkey_info *key_info = NULL;
	X509 *x = NULL;
	BIO *mem = NULL;
	unsigned char *buff = NULL, *ptr = NULL;
	int rv;

	LOG_FUNC_CALLED(ctx);
	if (out_key_object)
		*out_key_object = NULL;

	rv = sc_pkcs15_find_prkey_by_id(p15card, &((struct sc_pkcs15_cert_info *)cert_object->data)->id, &key_object);
	if (rv == SC_ERROR_OBJECT_NOT_FOUND)
		LOG_FUNC_RETURN(ctx, SC_SUCCESS);
	LOG_TEST_RET(ctx, rv, "Find private key error");

	key_info = (struct sc_pkcs15_prkey_info *) key_object->data;

	ERR_load_ERR_strings();
	ERR_load_crypto_strings();

	sc_log(ctx, "CertValue(%i) %p", cert_object->content.len, cert_object->content.value);
	mem = BIO_new_mem_buf(cert_object->content.value, cert_object->content.len);
	if (!mem)
		LOG_TEST_RET(ctx, SC_ERROR_INTERNAL, "MEM buffer allocation error");

	x = d2i_X509_bio(mem, NULL);
	if (!x)
		LOG_TEST_RET(ctx, SC_ERROR_INTERNAL, "x509 parse error");

	buff = OPENSSL_malloc(i2d_X509(x,NULL) + EVP_MAX_MD_SIZE);
	if (!buff)
		LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "OpenSSL allocation error");

	ptr = buff;
	rv = i2d_X509_NAME(X509_get_subject_name(x), &ptr);
	if (rv <= 0)
		LOG_TEST_RET(ctx, SC_ERROR_INTERNAL, "Get subject name error");

	key_info->subject.value = malloc(rv);
	if (!key_info->subject.value)
		LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Subject allocation error");

	memcpy(key_info->subject.value, buff, rv);
	key_info->subject.len = rv;

	strlcpy(key_object->label, cert_object->label, sizeof(key_object->label));

	rv = 0;

	if (x)
		X509_free(x);
	if (mem)
		BIO_free(mem);
	if (buff)
		OPENSSL_free(buff);

	ERR_clear_error();
	ERR_free_strings();

	if (out_key_object)
		*out_key_object = key_object;

	sc_log(ctx, "Subject %s", sc_dump_hex(key_info->subject.value, key_info->subject.len));
	LOG_FUNC_RETURN(ctx, rv);
#else
	LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
#endif
}
示例#10
0
// ----------------------------------------------------------------------------
// main()
// ----------------------------------------------------------------------------
int main( int argc, const char **argv )
{
	typedef std::list< std::string > file_list_t;
	file_list_t files;
	std::string pkg_file, cert_file, key_pass;

	for( int i = 1; i < argc; i++ )
	{
		if( 0 == strcmp( argv[ i ], "-V" ))
		{
			printf( "mkpkg v%s\n", VERSION );
			return 0;
		}
		else if( 0 == strcmp( argv[ i ], "-k" ))
		{
			if( argc == ++i )
			{
				printf( "-k: missing argument\n" );
				return 1;
			}
			cert_file = argv[ i ];
		}
		else if( 0 == strcmp( argv[ i ], "-p" ))
		{
			if( argc == ++i )
			{
				printf( "-p: missing argument\n" );
				return 1;
			}
			key_pass = argv[ i ];
		}
		else if( 0 == strcmp( argv[ i ], "-o" ))
		{
			if( argc == ++i )
			{
				printf( "-o: missing argument\n" );
				return 1;
			}
			pkg_file = argv[ i ];
		}
		else
			files.push_back( argv[ i ] );
	}

	if( pkg_file.empty() )
	{
		printf( "Missing package file name\n" );
		return 1;
	}
	if( cert_file.empty() )
		printf( " *** Package will not be signed ***\n" );
	if( files.empty() )
	{
		printf( "Missing package image files\n" );
		return 1;
	}

	OpenSSL_add_all_algorithms();

	// Load signing certificate
	X509 *cert = 0;
	RSA *key = 0;
	if( !cert_file.empty() )
	{
		FILE *fp = fopen( cert_file.c_str(), "r" );
		if( 0 == fp )
		{
			printf( "Failed to open signing cert: %s\n", cert_file.c_str() );
			return 1;
		}
		cert = PEM_read_X509( fp, 0, 0, 0 );
		key = PEM_read_RSAPrivateKey( fp, 0, password_cb, &key_pass );
		if( 0 == cert || 0 == key )
		{
			printf( "Failed to read signing cert\n" );
			return false;
		}
	}

	// Open the output file for writing
	wpt::fd fd;
	fd = open( pkg_file.c_str(), O_CREAT | O_RDWR | O_TRUNC, 0744 );
	if( !fd )
	{
		printf( "open( %s ) failed: (%i) %m\n", pkg_file.c_str(), errno );
		return 1;
	}

	// Begin hash
	SHA256_CTX sha256;
	memset( &sha256, 0, sizeof( sha256 ));
	SHA256_Init( &sha256 );

	// Write out installer...
	printf( "Writing installer.bin ... " );
	char *installer_data = _binary_installer_bin_start;
	unsigned int installer_size = (unsigned int)(unsigned long)&_binary_installer_bin_size;
	if( installer_size != write( fd, installer_data, installer_size ) )
	{
		printf( "write() failed: (%i) %m\n", errno );
		unlink( pkg_file.c_str() );
		return 1;
	}
	SHA256_Update( &sha256, installer_data, installer_size );
	printf( "done\n" );

	// Write out the files
	typedef std::list< entry_t > index_t;
	index_t index;
	for( file_list_t::iterator iter = files.begin(); iter != files.end(); iter++ )
	{
		std::string::size_type p = iter->find_first_of( ":" );
		std::string file = ( p != std::string::npos ? iter->substr( 0, p ) : *iter );
		std::string name = ( p != std::string::npos ? iter->substr( p + 1 ) : basename( iter->c_str() ) );

		entry_t entry;
		memset( &entry, 0, sizeof( entry ));
		snprintf( entry.name, sizeof( entry.name ), "%s", name.c_str() );

		printf( "Writing %s => %s ... ", file.c_str(), name.c_str() );
		if( !add_file( file, fd, sha256, entry ))
		{
			unlink( pkg_file.c_str() );
			return 1;
		}
		index.push_back( entry );
		printf( "done\n" );
	}

	// write out index
	printf( "Writing index ... " );
	unsigned int index_offset = lseek( fd, 0, SEEK_CUR );
	for( index_t::iterator i = index.begin(); i != index.end(); i++ )
	{
		entry_t &entry = *i;
		if( sizeof( entry ) != write( fd, &entry, sizeof( entry )))
		{
			unlink( pkg_file.c_str() );
			return 1;
		}
		SHA256_Update( &sha256, &entry, sizeof( entry ) );
	}
	printf( "done\n" );

	// Write signing certificate
	if( cert )
	{
		printf( "Writing signing certificate ... " );
		unsigned char cert_buffer[ 2048 ];
		unsigned char *p = cert_buffer;
		int len = i2d_X509( cert, &p );
		if( -1 == write( fd, cert_buffer, len ))
		{
			printf( "write() failed: (%i) %m\n", errno );
			unlink( pkg_file.c_str() );
			return 1;
		}
		SHA256_Update( &sha256, cert_buffer, len );
		X509_free( cert );
		printf( "done\n" );
	}

	// Add the footer
	printf( "Writing footer ... " );
	footer_t footer;
	memset( &footer, 0, sizeof( footer ));
	footer.ident = FTR_IDENT_V2;
	footer.index_offset = index_offset;
	footer.index_count = index.size();

	unsigned char hash[ 32 ];
	SHA256_Final( hash, &sha256 );

	// Sign
	if( key )
	{
		unsigned int sig_size = 0;
		int ret = RSA_sign( NID_sha1, hash, sizeof( hash ), footer.sig, &sig_size, key );
		RSA_free( key );
		if( 0 == ret )
		{
			printf( "RSA_sign() failed\n" );
			unlink( pkg_file.c_str() );
			return 1;
		}
	}

	footer.crc = ntohl( crc32( &footer, sizeof( footer ) - 4 ) );
	if( sizeof( footer_t ) != write( fd, &footer, sizeof( footer )) )
	{
		printf( "write() failed: (%i) %m\n", errno );
		unlink( pkg_file.c_str() );
		return 1;
	}
	printf( "done\n" );

	// done
	return 0;
}
示例#11
0
文件: p1_tls_drv.c 项目: runcom/tls
static ErlDrvSSizeT tls_drv_control(ErlDrvData handle,
			   unsigned int command,
			   char *buf, ErlDrvSizeT len,
			   char **rbuf, ErlDrvSizeT rlen)
{
   tls_data *d = (tls_data *)handle;
   int res;
   int size;
   ErlDrvBinary *b;
   X509 *cert;
   unsigned int flags = command;

   command &= 0xffff;

   ERR_clear_error();
   switch (command)
   {
      case SET_CERTIFICATE_FILE_ACCEPT:
      case SET_CERTIFICATE_FILE_CONNECT: {
	 time_t mtime = 0;
	 char *protocol_options = (buf + strlen(buf) + 1) + strlen(buf + strlen(buf) + 1) + 1;
	 char *po = strdup(protocol_options), delim[] = "|";
	 long options = 0L;

	 if (strlen(protocol_options) != 0) {
	   while ((po = strtok(po, delim)) != NULL) {
             set_option_flag(po, &options);
             po = NULL;
           }
	 }

	 SSL_CTX *ssl_ctx = hash_table_lookup(buf, &mtime);

	 if (is_key_file_modified(buf, &mtime) || ssl_ctx == NULL)
	 {
	    SSL_CTX *ctx;
	    char *ciphers;

	    hash_table_insert(buf, mtime, NULL);

	    ctx = SSL_CTX_new(SSLv23_method());
	    die_unless(ctx, "SSL_CTX_new failed");

	    res = SSL_CTX_use_certificate_chain_file(ctx, buf);
	    die_unless(res > 0, "SSL_CTX_use_certificate_file failed");

	    res = SSL_CTX_use_PrivateKey_file(ctx, buf, SSL_FILETYPE_PEM);
	    die_unless(res > 0, "SSL_CTX_use_PrivateKey_file failed");

	    res = SSL_CTX_check_private_key(ctx);
	    die_unless(res > 0, "SSL_CTX_check_private_key failed");

	    ciphers = buf + strlen(buf) + 1;
	    if (strlen(ciphers) == 0)
	       ciphers = CIPHERS;
	    SSL_CTX_set_cipher_list(ctx, ciphers);

#ifndef OPENSSL_NO_ECDH
	    if (command == SET_CERTIFICATE_FILE_ACCEPT) {
		setup_ecdh(ctx);
	    }
#endif
#ifndef OPENSSL_NO_DH
	    if (command == SET_CERTIFICATE_FILE_ACCEPT) {
		setup_dh(ctx);
	    }
#endif

	    SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
	    SSL_CTX_set_default_verify_paths(ctx);
#ifdef SSL_MODE_RELEASE_BUFFERS
	    SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
	    /* SSL_CTX_load_verify_locations(ctx, "/etc/ejabberd/ca_certificates.pem", NULL); */
	    /* SSL_CTX_load_verify_locations(ctx, NULL, "/etc/ejabberd/ca_certs/"); */

	    /* This IF is commented to allow verification in all cases: */
	    /* if (command == SET_CERTIFICATE_FILE_ACCEPT) */
	    /* { */
	       SSL_CTX_set_verify(ctx,
				  SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
				  verify_callback);
	    /* } */

	    SSL_CTX_set_info_callback(ctx, &ssl_info_callback);

	    ssl_ctx = ctx;
	    hash_table_insert(buf, mtime, ssl_ctx);
	 }

	 d->ssl = SSL_new(ssl_ctx);
	 die_unless(d->ssl, "SSL_new failed");

	 if (flags & VERIFY_NONE)
	    SSL_set_verify(d->ssl, SSL_VERIFY_NONE, verify_callback);

#ifdef SSL_OP_NO_COMPRESSION
	 if (flags & COMPRESSION_NONE)
	     SSL_set_options(d->ssl, SSL_OP_NO_COMPRESSION);
#endif

	 SSL_set_ex_data(d->ssl, ssl_index, d);

	 d->bio_read = BIO_new(BIO_s_mem());
	 d->bio_write = BIO_new(BIO_s_mem());

	 SSL_set_bio(d->ssl, d->bio_read, d->bio_write);

	 if (command == SET_CERTIFICATE_FILE_ACCEPT) {
	    options |= (SSL_OP_NO_TICKET|SSL_OP_ALL|SSL_OP_NO_SSLv2);

	    SSL_set_options(d->ssl, options);

	    SSL_set_accept_state(d->ssl);
	 } else {
	    options |= (SSL_OP_NO_TICKET|SSL_OP_NO_SSLv2);

	    SSL_set_options(d->ssl, options);

	    SSL_set_connect_state(d->ssl);
	 }
	 break;
      }
      case SET_ENCRYPTED_INPUT:
	 die_unless(d->ssl, "SSL not initialized");
	 BIO_write(d->bio_read, buf, len);
	 break;
      case SET_DECRYPTED_OUTPUT:
	 die_unless(d->ssl, "SSL not initialized");

	 res = SSL_write(d->ssl, buf, len);
	 if (res <= 0) 
	 {
	    res = SSL_get_error(d->ssl, res);
	    if (res == SSL_ERROR_WANT_READ || res == SSL_ERROR_WANT_WRITE) 
	    {
	       b = driver_alloc_binary(1);
	       b->orig_bytes[0] = 2;
	       *rbuf = (char *)b;
	       return 1;
	    } else {
	       die_unless(0, "SSL_write failed");
	    }
	 }
	 break;
      case GET_ENCRYPTED_OUTPUT:
	 die_unless(d->ssl, "SSL not initialized");
	 size = BIO_ctrl_pending(d->bio_write) + 1;
	 b = driver_alloc_binary(size);
	 b->orig_bytes[0] = 0;
	 BIO_read(d->bio_write, b->orig_bytes + 1, size - 1);
	 *rbuf = (char *)b;
	 return size;
      case GET_DECRYPTED_INPUT:
	 if (!SSL_is_init_finished(d->ssl))
	 {
	    res = SSL_do_handshake(d->ssl);
	    if (res <= 0)
	       die_unless(SSL_get_error(d->ssl, res) == SSL_ERROR_WANT_READ,
			  "SSL_do_handshake failed");
	 }
	 if (SSL_is_init_finished(d->ssl)) {
	    size_t req_size = 0;
	    if (len == 4)
	    {
	       unsigned char *b = (unsigned char *)buf;
	       req_size =
		  (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
	    }
	    size = BUF_SIZE + 1;
	    rlen = 1;
	    b = driver_alloc_binary(size);
	    b->orig_bytes[0] = 0;

	    res = 0;

	    while ((req_size == 0 || rlen < req_size + 1) &&
		   (res = SSL_read(d->ssl,
				   b->orig_bytes + rlen,
				   (req_size == 0 || req_size + 1 >= size) ?
				   size - rlen : req_size + 1 - rlen)) > 0)
	    {
	       //printf("%d bytes of decrypted data read from state machine\r\n",res);
	       rlen += res;
	       if (size - rlen < BUF_SIZE) {
		  size *= 2;
		  b = driver_realloc_binary(b, size);
	       }
	    }

	    if (d->handshakes > 1) {
	       char *error = "client renegotiations forbidden";
	       int error_len = strlen(error);
	       rlen = error_len + 1;
	       b = driver_alloc_binary(rlen);
	       b->orig_bytes[0] = 1;
	       strncpy(b->orig_bytes + 1, error, error_len);
	       *rbuf = (char *)b;
	       return rlen;
	    }

	    if (res < 0)
	    {
	       int err = SSL_get_error(d->ssl, res);

	       if (err == SSL_ERROR_WANT_READ)
	       {
		  //printf("SSL_read wants more data\r\n");
		  //return 0;
	       }
	       // TODO
	    }
	    b = driver_realloc_binary(b, rlen);
	    *rbuf = (char *)b;
	    return rlen;
	 }
	 break;
      case GET_PEER_CERTIFICATE:
	 cert = SSL_get_peer_certificate(d->ssl);
	 if (cert == NULL)
	 {
	    b = driver_alloc_binary(1);
	    b->orig_bytes[0] = 1;
	    *rbuf = (char *)b;
	    return 1;
	 } else {
	    unsigned char *tmp_buf;
	    rlen = i2d_X509(cert, NULL);
	    if (rlen >= 0)
	    {
	       rlen++;
	       b = driver_alloc_binary(rlen);
	       b->orig_bytes[0] = 0;
	       tmp_buf = (unsigned char *)&b->orig_bytes[1];
	       i2d_X509(cert, &tmp_buf);
	       X509_free(cert);
	       *rbuf = (char *)b;
	       return rlen;
	    } else
	       X509_free(cert);
	 }
	 break;
      case GET_VERIFY_RESULT:
	 b = driver_alloc_binary(1);
	 b->orig_bytes[0] = SSL_get_verify_result(d->ssl);
	 *rbuf = (char *)b;
	 return 1;
	 break;
   }

   b = driver_alloc_binary(1);
   b->orig_bytes[0] = 0;
   *rbuf = (char *)b;
   return 1;
}
示例#12
0
static int execute_test_large_message(const SSL_METHOD *smeth,
                                      const SSL_METHOD *cmeth, int read_ahead)
{
    SSL_CTX *cctx = NULL, *sctx = NULL;
    SSL *clientssl = NULL, *serverssl = NULL;
    int testresult = 0;
    int i;
    BIO *certbio = BIO_new_file(cert, "r");
    X509 *chaincert = NULL;
    int certlen;

    if (certbio == NULL) {
        printf("Can't load the certficate file\n");
        goto end;
    }
    chaincert = PEM_read_bio_X509(certbio, NULL, NULL, NULL);
    BIO_free(certbio);
    certbio = NULL;
    if (chaincert == NULL) {
        printf("Unable to load certificate for chain\n");
        goto end;
    }

    if (!create_ssl_ctx_pair(smeth, cmeth, &sctx,
                             &cctx, cert, privkey)) {
        printf("Unable to create SSL_CTX pair\n");
        goto end;
    }

    if(read_ahead) {
        /*
         * Test that read_ahead works correctly when dealing with large
         * records
         */
        SSL_CTX_set_read_ahead(cctx, 1);
    }

    /*
     * We assume the supplied certificate is big enough so that if we add
     * NUM_EXTRA_CERTS it will make the overall message large enough. The
     * default buffer size is requested to be 16k, but due to the way BUF_MEM
     * works, it ends up allocing a little over 21k (16 * 4/3). So, in this test
     * we need to have a message larger than that.
     */
    certlen = i2d_X509(chaincert, NULL);
    OPENSSL_assert((certlen * NUM_EXTRA_CERTS)
                   > ((SSL3_RT_MAX_PLAIN_LENGTH * 4) / 3));
    for (i = 0; i < NUM_EXTRA_CERTS; i++) {
        if (!X509_up_ref(chaincert)) {
            printf("Unable to up ref cert\n");
            goto end;
        }
        if (!SSL_CTX_add_extra_chain_cert(sctx, chaincert)) {
            printf("Unable to add extra chain cert %d\n", i);
            X509_free(chaincert);
            goto end;
        }
    }

    if (!create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL)) {
        printf("Unable to create SSL objects\n");
        goto end;
    }

    if (!create_ssl_connection(serverssl, clientssl)) {
        printf("Unable to create SSL connection\n");
        goto end;
    }

    testresult = 1;

 end:
    X509_free(chaincert);
    SSL_free(serverssl);
    SSL_free(clientssl);
    SSL_CTX_free(sctx);
    SSL_CTX_free(cctx);

    return testresult;
}
示例#13
0
ldns_status
ldns_dane_cert2rdf(ldns_rdf** rdf, X509* cert,
		ldns_tlsa_selector      selector,
		ldns_tlsa_matching_type matching_type)
{
	unsigned char* buf = NULL;
	size_t len;

	X509_PUBKEY* xpubkey;
	EVP_PKEY* epubkey;

	unsigned char* digest;

	assert(rdf != NULL);
	assert(cert != NULL);

	switch(selector) {
	case LDNS_TLSA_SELECTOR_FULL_CERTIFICATE:

		len = (size_t)i2d_X509(cert, &buf);
		break;

	case LDNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO:

#ifndef S_SPLINT_S
		xpubkey = X509_get_X509_PUBKEY(cert);
#endif
		if (! xpubkey) {
			return LDNS_STATUS_SSL_ERR;
		}
		epubkey = X509_PUBKEY_get(xpubkey);
		if (! epubkey) {
			return LDNS_STATUS_SSL_ERR;
		}
		len = (size_t)i2d_PUBKEY(epubkey, &buf);
		break;
	
	default:
		return LDNS_STATUS_DANE_UNKNOWN_SELECTOR;
	}

	switch(matching_type) {
	case LDNS_TLSA_MATCHING_TYPE_NO_HASH_USED:

		*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, len, buf);
		
		return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
		break;
	
	case LDNS_TLSA_MATCHING_TYPE_SHA256:

		digest = LDNS_XMALLOC(unsigned char, SHA256_DIGEST_LENGTH);
		if (digest == NULL) {
			LDNS_FREE(buf);
			return LDNS_STATUS_MEM_ERR;
		}
		(void) ldns_sha256(buf, (unsigned int)len, digest);
		*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, SHA256_DIGEST_LENGTH,
				digest);
		LDNS_FREE(buf);

		return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
		break;

	case LDNS_TLSA_MATCHING_TYPE_SHA512:

		digest = LDNS_XMALLOC(unsigned char, SHA512_DIGEST_LENGTH);
		if (digest == NULL) {
			LDNS_FREE(buf);
			return LDNS_STATUS_MEM_ERR;
		}
		(void) ldns_sha512(buf, (unsigned int)len, digest);
		*rdf = ldns_rdf_new(LDNS_RDF_TYPE_HEX, SHA512_DIGEST_LENGTH,
				digest);
		LDNS_FREE(buf);

		return *rdf ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR;
		break;
	
	default:
		LDNS_FREE(buf);
		return LDNS_STATUS_DANE_UNKNOWN_MATCHING_TYPE;
	}
}
示例#14
0
/*============================================================================
 * OpcUa_P_OpenSSL_X509_LoadFromFile
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_X509_LoadFromFile(
    OpcUa_StringA               a_fileName,
    OpcUa_P_FileFormat          a_fileFormat,
    OpcUa_StringA               a_sPassword,        /* optional: just for OpcUa_PKCS12 */
    OpcUa_ByteString*           a_pCertificate)
{
    BIO*            pCertFile       = OpcUa_Null;
    X509*           pCertX509       = OpcUa_Null;
    PKCS12*         pPKCS12Cert     = OpcUa_Null;

OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "X509_LoadFromFile");

    /* check filename */
    if(OpcUa_P_String_strlen(a_fileName) < 1)
    {
        uStatus = OpcUa_BadInvalidArgument;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* import certificate from file by the given encoding type */
    pCertFile = BIO_new_file((const char*)a_fileName, "r");
    OpcUa_ReturnErrorIfArgumentNull(pCertFile);

    switch(a_fileFormat)
    {
    case OpcUa_Crypto_Encoding_DER:
        {

            pCertX509 = d2i_X509_bio(pCertFile,      /* sourcefile */
                                     (X509**)NULL);  /* target (if preallocated) */
            break;
        }
    case OpcUa_Crypto_Encoding_PEM:
        {

            pCertX509 = PEM_read_bio_X509(  pCertFile,          /* sourcefile */
                                            (X509**)OpcUa_Null, /* target (if preallocated) */
                                            OpcUa_Null,         /* password callback function */
                                            OpcUa_Null);        /* passphrase or callback data */
            break;
        }
    case OpcUa_Crypto_Encoding_PKCS12:
        {
            d2i_PKCS12_bio(pCertFile, &pPKCS12Cert);

            PKCS12_parse(pPKCS12Cert, a_sPassword, OpcUa_Null, &pCertX509, OpcUa_Null);

            if(pPKCS12Cert != OpcUa_Null)
            {
                PKCS12_free(pPKCS12Cert);
                /*OPENSSL_free(pPKCS12Cert);*/
            }

            break;
        }
    default:
        {
            BIO_free(pCertFile);
            return OpcUa_BadNotSupported;
        }
    }

    BIO_free(pCertFile);
    pCertFile = OpcUa_Null;

    if(pCertX509 == OpcUa_Null)
    {
        /* error in OpenSSL - maybe certificate file was corrupt */
        return OpcUa_Bad;
    }

    /* prepare container */
    memset(a_pCertificate, 0, sizeof(OpcUa_ByteString));

    /* get required length for conversion target buffer */
    a_pCertificate->Length = i2d_X509(  pCertX509,
                                            NULL);

    if(a_pCertificate->Length <= 0)
    {
        /* conversion to DER not possible */
        uStatus = OpcUa_Bad;
    }

    /* allocate conversion target buffer */
    a_pCertificate->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pCertificate->Length);
    OpcUa_GotoErrorIfAllocFailed(a_pCertificate->Data);

    /* convert into DER */
    a_pCertificate->Length = i2d_X509(  pCertX509,
                                            &(a_pCertificate->Data));
    if(a_pCertificate->Length <= 0)
    {
        /* conversion to DER not possible */
        uStatus = OpcUa_Bad;
    }
    else
    {
        /* correct pointer incrementation by i2d_X509() */
        a_pCertificate->Data -= a_pCertificate->Length;
    }

    X509_free(pCertX509);

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

    if(pCertX509 != OpcUa_Null)
    {
        X509_free(pCertX509);
    }

    if(pPKCS12Cert != OpcUa_Null)
    {
        OPENSSL_free(pPKCS12Cert);
    }

    if(a_pCertificate->Data != OpcUa_Null)
    {
        OpcUa_P_Memory_Free(a_pCertificate->Data);
        a_pCertificate->Data = OpcUa_Null;
    }

    if(pCertFile != OpcUa_Null)
    {
        BIO_free(pCertFile);
    }

OpcUa_FinishErrorHandling;
}
示例#15
0
extern "C" int32_t CryptoNative_EncodeX509(X509* x, uint8_t* buf)
{
    return i2d_X509(x, &buf);
}
示例#16
0
static int
mta_verify_certificate(struct mta_session *s)
{
#define MAX_CERTS	16
#define MAX_CERT_LEN	(MAX_IMSGSIZE - (IMSG_HEADER_SIZE + sizeof(req_ca_vrfy)))
	struct ca_vrfy_req_msg	req_ca_vrfy;
	struct iovec		iov[2];
	X509		       *x;
	STACK_OF(X509)	       *xchain;
	const char	       *name;
	unsigned char	       *cert_der[MAX_CERTS];
	int			cert_len[MAX_CERTS];
	int			i, cert_count, res;

	res = 0;
	memset(cert_der, 0, sizeof(cert_der));
	memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy);

	/* Send the client certificate */
	if (s->relay->ca_name) {
		name = s->relay->ca_name;
		req_ca_vrfy.fallback = 0;
	}
	else {
		name = s->helo;
		req_ca_vrfy.fallback = 1;
	}
	if (strlcpy(req_ca_vrfy.name, name, sizeof req_ca_vrfy.name)
	    >= sizeof req_ca_vrfy.name)
		return 0;

	x = SSL_get_peer_certificate(s->io.ssl);
	if (x == NULL)
		return 0;
	xchain = SSL_get_peer_cert_chain(s->io.ssl);

	/*
	 * Client provided a certificate and possibly a certificate chain.
	 * SMTP can't verify because it does not have the information that
	 * it needs, instead it will pass the certificate and chain to the
	 * lookup process and wait for a reply.
	 *
	 */

	cert_len[0] = i2d_X509(x, &cert_der[0]);
	X509_free(x);

	if (cert_len[0] < 0) {
		log_warnx("warn: failed to encode certificate");
		goto end;
	}
	log_debug("debug: certificate 0: len=%d", cert_len[0]);
	if (cert_len[0] > (int)MAX_CERT_LEN) {
		log_warnx("warn: certificate too long");
		goto end;
	}

	if (xchain) {
		cert_count = sk_X509_num(xchain);
		log_debug("debug: certificate chain len: %d", cert_count);
		if (cert_count >= MAX_CERTS) {
			log_warnx("warn: certificate chain too long");
			goto end;
		}
	}
	else
		cert_count = 0;

	for (i = 0; i < cert_count; ++i) {
		x = sk_X509_value(xchain, i);
		cert_len[i+1] = i2d_X509(x, &cert_der[i+1]);
		if (cert_len[i+1] < 0) {
			log_warnx("warn: failed to encode certificate");
			goto end;
		}
		log_debug("debug: certificate %i: len=%d", i+1, cert_len[i+1]);
		if (cert_len[i+1] > (int)MAX_CERT_LEN) {
			log_warnx("warn: certificate too long");
			goto end;
		}
	}

	tree_xset(&wait_ssl_verify, s->id, s);
	s->flags |= MTA_WAIT;

	/* Send the client certificate */
	req_ca_vrfy.reqid = s->id;
	req_ca_vrfy.cert_len = cert_len[0];
	req_ca_vrfy.n_chain = cert_count;
	iov[0].iov_base = &req_ca_vrfy;
	iov[0].iov_len = sizeof(req_ca_vrfy);
	iov[1].iov_base = cert_der[0];
	iov[1].iov_len = cert_len[0];
	m_composev(p_lka, IMSG_MTA_TLS_VERIFY_CERT, 0, 0, -1,
	    iov, nitems(iov));

	memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy);
	req_ca_vrfy.reqid = s->id;

	/* Send the chain, one cert at a time */
	for (i = 0; i < cert_count; ++i) {
		req_ca_vrfy.cert_len = cert_len[i+1];
		iov[1].iov_base = cert_der[i+1];
		iov[1].iov_len  = cert_len[i+1];
		m_composev(p_lka, IMSG_MTA_TLS_VERIFY_CHAIN, 0, 0, -1,
		    iov, nitems(iov));
	}

	/* Tell lookup process that it can start verifying, we're done */
	memset(&req_ca_vrfy, 0, sizeof req_ca_vrfy);
	req_ca_vrfy.reqid = s->id;
	m_compose(p_lka, IMSG_MTA_TLS_VERIFY, 0, 0, -1,
	    &req_ca_vrfy, sizeof req_ca_vrfy);

	res = 1;

    end:
	for (i = 0; i < MAX_CERTS; ++i)
		free(cert_der[i]);

	return res;
}
示例#17
0
void Server::initializeCert() {
	QByteArray crt, key, pass, dhparams;

	crt = getConf("certificate", QString()).toByteArray();
	key = getConf("key", QString()).toByteArray();
	pass = getConf("passphrase", QByteArray()).toByteArray();
	dhparams = getConf("sslDHParams", Meta::mp.qbaDHParams).toByteArray();

	QList<QSslCertificate> ql;

	// Attempt to load key as an RSA key or a DSA key
	if (! key.isEmpty()) {
		qskKey = QSslKey(key, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, pass);
		if (qskKey.isNull())
			qskKey = QSslKey(key, QSsl::Dsa, QSsl::Pem, QSsl::PrivateKey, pass);
	}

	// If we still can't load the key, try loading any keys from the certificate
	if (qskKey.isNull() && ! crt.isEmpty()) {
		qskKey = QSslKey(crt, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, pass);
		if (qskKey.isNull())
			qskKey = QSslKey(crt, QSsl::Dsa, QSsl::Pem, QSsl::PrivateKey, pass);
	}

	// If have a key, walk the list of certs, find the one for our key,
	// remove any certs for our key from the list, what's left is part of
	// the CA certificate chain.
	if (! qskKey.isNull()) {
		ql << QSslCertificate::fromData(crt);
		ql << QSslCertificate::fromData(key);
		for (int i=0;i<ql.size();++i) {
			const QSslCertificate &c = ql.at(i);
			if (isKeyForCert(qskKey, c)) {
				qscCert = c;
				ql.removeAt(i);
			}
		}
		qlCA = ql;
	}

#if defined(USE_QSSLDIFFIEHELLMANPARAMETERS)
	if (! dhparams.isEmpty()) {
		QSslDiffieHellmanParameters qdhp = QSslDiffieHellmanParameters(dhparams);
		if (qdhp.isValid()) {
			qsdhpDHParams = qdhp;
		} else {
			log(QString::fromLatin1("Unable to use specified Diffie-Hellman parameters (sslDHParams): %1").arg(qdhp.errorString()));
		}
	}
#else
	if (! dhparams.isEmpty()) {
		log("Diffie-Hellman parameters (sslDHParams) were specified, but will not be used. This version of Murmur does not support Diffie-Hellman parameters.");
	}
#endif

	QString issuer;
#if QT_VERSION >= 0x050000
	QStringList issuerNames = qscCert.issuerInfo(QSslCertificate::CommonName);
	if (! issuerNames.isEmpty()) {
		issuer = issuerNames.first();
	}
#else
	issuer = qscCert.issuerInfo(QSslCertificate::CommonName);
#endif

	// Really old certs/keys are no good, throw them away so we can
	// generate a new one below.
	if (issuer == QString::fromUtf8("Murmur Autogenerated Certificate")) {
		log("Old autogenerated certificate is unusable for registration, invalidating it");
		qscCert = QSslCertificate();
		qskKey = QSslKey();
	}

	// If we have a cert, and it's a self-signed one, but we're binding to
	// all the same addresses as the Meta server is, use it's cert instead.
	// This allows a self-signed certificate generated by Murmur to be
	// replaced by a CA-signed certificate in the .ini file.
	if (!qscCert.isNull() && issuer == QString::fromUtf8("Murmur Autogenerated Certificate v2") && ! Meta::mp.qscCert.isNull() && ! Meta::mp.qskKey.isNull() && (Meta::mp.qlBind == qlBind)) {
		qscCert = Meta::mp.qscCert;
		qskKey = Meta::mp.qskKey;
	}

	// If we still don't have a certificate by now, try to load the one from Meta
	if (qscCert.isNull() || qskKey.isNull()) {
		if (! key.isEmpty() || ! crt.isEmpty()) {
			log("Certificate specified, but failed to load.");
		}
		qskKey = Meta::mp.qskKey;
		qscCert = Meta::mp.qscCert;

		// If loading from Meta doesn't work, build+sign a new one
		if (qscCert.isNull() || qskKey.isNull()) {
			log("Generating new server certificate.");

			CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);

			X509 *x509 = X509_new();
			EVP_PKEY *pkey = EVP_PKEY_new();
			RSA *rsa = RSA_generate_key(2048,RSA_F4,NULL,NULL);
			EVP_PKEY_assign_RSA(pkey, rsa);

			X509_set_version(x509, 2);
			ASN1_INTEGER_set(X509_get_serialNumber(x509),1);
			X509_gmtime_adj(X509_get_notBefore(x509),0);
			X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365*20);
			X509_set_pubkey(x509, pkey);

			X509_NAME *name=X509_get_subject_name(x509);

			X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, reinterpret_cast<unsigned char *>(const_cast<char *>("Murmur Autogenerated Certificate v2")), -1, -1, 0);
			X509_set_issuer_name(x509, name);
			add_ext(x509, NID_basic_constraints, SSL_STRING("critical,CA:FALSE"));
			add_ext(x509, NID_ext_key_usage, SSL_STRING("serverAuth,clientAuth"));
			add_ext(x509, NID_subject_key_identifier, SSL_STRING("hash"));
			add_ext(x509, NID_netscape_comment, SSL_STRING("Generated from murmur"));

			X509_sign(x509, pkey, EVP_sha1());

			crt.resize(i2d_X509(x509, NULL));
			unsigned char *dptr=reinterpret_cast<unsigned char *>(crt.data());
			i2d_X509(x509, &dptr);

			qscCert = QSslCertificate(crt, QSsl::Der);
			if (qscCert.isNull())
				log("Certificate generation failed");

			key.resize(i2d_PrivateKey(pkey, NULL));
			dptr=reinterpret_cast<unsigned char *>(key.data());
			i2d_PrivateKey(pkey, &dptr);

			qskKey = QSslKey(key, QSsl::Rsa, QSsl::Der);
			if (qskKey.isNull())
				log("Key generation failed");

			setConf("certificate", qscCert.toPem());
			setConf("key", qskKey.toPem());
		}
	}

#if defined(USE_QSSLDIFFIEHELLMANPARAMETERS)
	if (qsdhpDHParams.isEmpty()) {
		log("Generating new server 2048-bit Diffie-Hellman parameters. This could take a while...");

		DH *dh = DH_new();
		if (dh == NULL) {
			qFatal("DH_new failed: unable to generate Diffie-Hellman parameters for virtual server");
		}

		// Generate DH params.
		// We register a status callback in order to update the UI
		// for Murmur on Windows. We don't show the actual status,
		// but we do it to keep Murmur on Windows responsive while
		// generating the parameters.
		BN_GENCB cb;
		memset(&cb, 0, sizeof(BN_GENCB));
		BN_GENCB_set(&cb, dh_progress, NULL);
		if (DH_generate_parameters_ex(dh, 2048, 2, &cb) == 0) {
			qFatal("DH_generate_parameters_ex failed: unable to generate Diffie-Hellman parameters for virtual server");
		}

		BIO *mem = BIO_new(BIO_s_mem());
		if (PEM_write_bio_DHparams(mem, dh) == 0) {
			qFatal("PEM_write_bio_DHparams failed: unable to write generated Diffie-Hellman parameters to memory");
		}

		char *pem = NULL;
		long len = BIO_get_mem_data(mem, &pem);
		if (len <= 0) {
			qFatal("BIO_get_mem_data returned an empty or invalid buffer");
		}

		QByteArray pemdh(pem, len);
		QSslDiffieHellmanParameters qdhp(pemdh);
		if (!qdhp.isValid()) {
			qFatal("QSslDiffieHellmanParameters: unable to import generated Diffie-HellmanParameters: %s", qdhp.errorString().toStdString().c_str());
		}

		qsdhpDHParams = qdhp;
		setConf("sslDHParams", pemdh);

		BIO_free(mem);
		DH_free(dh);
	}
#endif

	// Drain OpenSSL's per-thread error queue
	// to ensure that errors from the operations
	// we've done in here do not leak out into
	// Qt's SSL module.
	//
	// If an error leaks, it can break all connections
	// to the server because each invocation of Qt's SSL
	// read callback checks OpenSSL's per-thread error
	// queue (albeit indirectly, via SSL_get_error()).
	// Qt expects any errors returned from SSL_get_error()
	// to be related to the QSslSocket it is currently
	// processing -- which is the obvious thing to expect:
	// SSL_get_error() takes a pointer to an SSL object
	// and the return code of the failed operation.
	// However, it is also documented as:
	//
	//  "In addition to ssl and ret, SSL_get_error()
	//   inspects the current thread's OpenSSL error
	//   queue."
	//
	// So, if any OpenSSL operation on the main thread
	// forgets to clear the error queue, those errors
	// *will* leak into other things that *do* error
	// checking. In our case, into Qt's SSL read callback,
	// resulting in all clients being disconnected.
	ERR_clear_error();
}
/**
 * @brief Inquire Sec Context by OID
 * @ingroup globus_gsi_gssapi_extensions
 */
OM_uint32
GSS_CALLCONV gss_inquire_sec_context_by_oid(
    OM_uint32 *                         minor_status,
    const gss_ctx_id_t                  context_handle,
    const gss_OID                       desired_object,
    gss_buffer_set_t *                  data_set)
{
    OM_uint32                           major_status = GSS_S_COMPLETE;
    OM_uint32                           local_minor_status;
    gss_ctx_id_desc *                   context = NULL;
    int                                 found_index;
    int                                 chain_index;
    int                                 cert_count;
    X509_EXTENSION *                    extension;
    X509 *                              cert = NULL;
    STACK_OF(X509) *                    cert_chain = NULL;
    ASN1_OBJECT *                       asn1_desired_obj = NULL;
    ASN1_OCTET_STRING *                 asn1_oct_string;
    gss_buffer_desc                     data_set_buffer = GSS_C_EMPTY_BUFFER;
    globus_result_t                     local_result = GLOBUS_SUCCESS;
    unsigned char *                     tmp_ptr;
    static char *                       _function_name_ =
        "gss_inquire_sec_context_by_oid";
    GLOBUS_I_GSI_GSSAPI_DEBUG_ENTER;

    /* parameter checking goes here */

    if(minor_status == NULL)
    {
        GLOBUS_GSI_GSSAPI_ERROR_RESULT(
            minor_status,
            GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT,
            (_GGSL("Invalid minor_status (NULL) passed to function")));
        major_status = GSS_S_FAILURE;
        goto exit;
    }
    
    if(context_handle == GSS_C_NO_CONTEXT)
    {
        GLOBUS_GSI_GSSAPI_ERROR_RESULT(
            minor_status,
            GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT,
            (_GGSL("Invalid context_handle passed to function")));
        major_status = GSS_S_FAILURE;
        goto exit;
    }

    *minor_status = (OM_uint32) GLOBUS_SUCCESS;
    context = (gss_ctx_id_desc *) context_handle;

    if(desired_object == GSS_C_NO_OID)
    {
        GLOBUS_GSI_GSSAPI_ERROR_RESULT(
            minor_status,
            GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT,
            (_GGSL("Invalid desired_object passed to function")));
        major_status = GSS_S_FAILURE;
        goto exit;
    }

    if(data_set == NULL)
    {
        GLOBUS_GSI_GSSAPI_ERROR_RESULT(
            minor_status,
            GLOBUS_GSI_GSSAPI_ERROR_BAD_ARGUMENT,
            (_GGSL("Invalid data_set (NULL) passed to function")));
        major_status = GSS_S_FAILURE;
        goto exit;
    }

    *data_set = NULL;

    /* lock the context mutex */
    globus_mutex_lock(&context->mutex);

    local_result = 
        globus_gsi_callback_get_cert_depth(context->callback_data,
                                           &cert_count);
    if(local_result != GLOBUS_SUCCESS)
    {
        GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
            minor_status, local_result,
            GLOBUS_GSI_GSSAPI_ERROR_WITH_CALLBACK_DATA);
        major_status = GSS_S_FAILURE;
        goto unlock_exit;
    }

    if(cert_count == 0)
    {
        goto unlock_exit;
    }
    
    major_status = gss_create_empty_buffer_set(&local_minor_status, data_set);

    if(GSS_ERROR(major_status))
    {
        GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
            minor_status, local_minor_status,
            GLOBUS_GSI_GSSAPI_ERROR_WITH_BUFFER);
        goto unlock_exit;
    }
    
    local_result = globus_gsi_callback_get_cert_chain(
        context->callback_data,
        &cert_chain);
    if(local_result != GLOBUS_SUCCESS)
    {
        GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
            minor_status, local_result,
            GLOBUS_GSI_GSSAPI_ERROR_WITH_CALLBACK_DATA);
        major_status = GSS_S_FAILURE;
        cert_chain = NULL;
        goto unlock_exit;
    }

    if(((gss_OID_desc *)desired_object)->length !=
       gss_ext_x509_cert_chain_oid->length ||
       memcmp(((gss_OID_desc *)desired_object)->elements,
              gss_ext_x509_cert_chain_oid->elements,
              gss_ext_x509_cert_chain_oid->length))
    {
        /* figure out what object was asked for */
        
        asn1_desired_obj = ASN1_OBJECT_new();
        if(!asn1_desired_obj)
        {
            GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT(
                minor_status,
                GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL,
                (_GGSL("Couldn't create ASN1 object")));
            major_status = GSS_S_FAILURE;
            goto unlock_exit;
        }

        asn1_desired_obj->length = ((gss_OID_desc *)desired_object)->length;
        asn1_desired_obj->data = ((gss_OID_desc *)desired_object)->elements;

        found_index = -1;

        for(chain_index = 0; chain_index < cert_count; chain_index++)
        {
            cert = sk_X509_value(cert_chain, chain_index);

            data_set_buffer.value = NULL;
            data_set_buffer.length = 0;

            found_index = X509_get_ext_by_OBJ(cert, 
                                              asn1_desired_obj, 
                                              found_index);
        
            if(found_index >= 0)
            {
                extension = X509_get_ext(cert, found_index);
                if(!extension)
                {
                    GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT(
                        minor_status,
                        GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL,
                        (_GGSL("Couldn't get extension at index %d "
                         "from cert in credential."), found_index));
                    major_status = GSS_S_FAILURE;
                    goto unlock_exit;
                }

                asn1_oct_string = X509_EXTENSION_get_data(extension);
                if(!asn1_oct_string)
                {
                    GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT(
                        minor_status,
                        GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL,
                        (_GGSL("Couldn't get cert extension in the form of an "
                         "ASN1 octet string.")));
                    major_status = GSS_S_FAILURE;
                    goto unlock_exit;
                }

                asn1_oct_string = ASN1_OCTET_STRING_dup(asn1_oct_string);

                if(!asn1_oct_string)
                {
                    GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT(
                        minor_status,
                        GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL,
                        (_GGSL("Failed to make copy of extension data")));
                    major_status = GSS_S_FAILURE;
                    goto unlock_exit;
                }

                data_set_buffer.value = asn1_oct_string->data;
                data_set_buffer.length = asn1_oct_string->length;

                OPENSSL_free(asn1_oct_string);
            
                major_status = gss_add_buffer_set_member(
                    &local_minor_status,
                    &data_set_buffer,
                    data_set);
                if(GSS_ERROR(major_status))
                {
                    GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
                        minor_status, local_minor_status,
                        GLOBUS_GSI_GSSAPI_ERROR_WITH_BUFFER);
                    goto unlock_exit;
                }
            }
        } 
    }
    else
    {
        for(chain_index = 0; chain_index < cert_count; chain_index++)
        {
            int certlen;
            cert = sk_X509_value(cert_chain, chain_index);

            certlen = i2d_X509(cert, NULL);
            data_set_buffer.length = certlen;

            if (certlen < 0)
            {
                GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT(
                    minor_status,
                    GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL,
                    (_GGSL("Failed to serialize certificate")));
                major_status = GSS_S_FAILURE;
                goto unlock_exit;                
            }
            
            tmp_ptr = realloc(data_set_buffer.value,
                              data_set_buffer.length);

            if(tmp_ptr == NULL)
            {
                GLOBUS_GSI_GSSAPI_MALLOC_ERROR(minor_status);
                major_status = GSS_S_FAILURE;
                goto unlock_exit;                
            }

            data_set_buffer.value = tmp_ptr;
            
            if(i2d_X509(cert,&tmp_ptr) < 0)
            {
                free(data_set_buffer.value);
                GLOBUS_GSI_GSSAPI_OPENSSL_ERROR_RESULT(
                    minor_status,
                    GLOBUS_GSI_GSSAPI_ERROR_WITH_OPENSSL,
                    (_GGSL("Failed to serialize certificate")));
                major_status = GSS_S_FAILURE;
                goto unlock_exit;                
            }

            major_status = gss_add_buffer_set_member(
                &local_minor_status,
                &data_set_buffer,
                data_set);
            if(GSS_ERROR(major_status))
            {
                GLOBUS_GSI_GSSAPI_ERROR_CHAIN_RESULT(
                    minor_status, local_minor_status,
                    GLOBUS_GSI_GSSAPI_ERROR_WITH_BUFFER);
                goto unlock_exit;
            }
        }
        
        if(data_set_buffer.value != NULL)
        {
            free(data_set_buffer.value);
        }
    }

unlock_exit:
    /* unlock the context mutex */
    globus_mutex_unlock(&context->mutex);

exit:
    if (asn1_desired_obj != NULL)
    {
        ASN1_OBJECT_free(asn1_desired_obj);
    }
    if(cert_chain != NULL)
    {
        sk_X509_pop_free(cert_chain, X509_free);
    }
    
    GLOBUS_I_GSI_GSSAPI_DEBUG_EXIT;
    return major_status;
}
CK_RV PKCS11_Objects_OpenSSL::GetAttributeValue(Cryptoki_Session_Context* pSessionCtx, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
{
    OBJECT_DATA* pObj = PKCS11_Objects_OpenSSL::GetObjectFromHandle(pSessionCtx, hObject);

    if(pObj == NULL) return CKR_OBJECT_HANDLE_INVALID;

    if(pObj->Type == CertificateType)
    {
        CERT_DATA* pCertData = (CERT_DATA*)pObj->Data;
        X509* pCert = pCertData->cert;
        UINT32 valLen = 0;
    
        for(int i=0; i<(int)ulCount; i++)
        {
            switch(pTemplate[i].type)
            {
                case CKA_CLASS:
                    *(INT32*)pTemplate[i].pValue = SwapEndianIfBEc32(CKO_CERTIFICATE);
                    break;
                case CKA_PRIVATE:
                    *(INT32*)pTemplate[i].pValue = SwapEndianIfBEc32(pCertData->privKeyData.key == NULL ? 0 : 1);
                    valLen = sizeof(INT32);
                    break;

                case CKA_VALUE_BITS:
                    {
                        *(INT32*)pTemplate[i].pValue = SwapEndianIfBEc32(pCertData->pubKeyData.size);
                        valLen = sizeof(INT32);
                    }
                    break;
                    
                case CKA_KEY_TYPE:
                    {
                        *(UINT32*)pTemplate[i].pValue = SwapEndianIfBEc32(pCertData->pubKeyData.type);
                        valLen = sizeof(UINT32);
                    }
                    break;

                case CKA_ISSUER:
                    {
                        char* name=X509_NAME_oneline(X509_get_issuer_name(pCert),NULL,0);
                        valLen = TINYCLR_SSL_STRLEN(name) + 1;

                        if(valLen > pTemplate[i].ulValueLen) valLen = pTemplate[i].ulValueLen;
                        
                        hal_strcpy_s((char*)pTemplate[i].pValue, valLen, name);
                        OPENSSL_free(name);
                    }
                    break;

                case CKA_SUBJECT:
                    {
                        char* subject=X509_NAME_oneline(X509_get_subject_name(pCert),NULL,0);
                        valLen = TINYCLR_SSL_STRLEN(subject) + 1;

                        if(valLen > pTemplate[i].ulValueLen) valLen = pTemplate[i].ulValueLen;
                        
                        hal_strcpy_s((char*)pTemplate[i].pValue, valLen, subject);
                        OPENSSL_free(subject);
                    }
                    break;

                case CKA_SERIAL_NUMBER:
                    {
                        ASN1_INTEGER* asn = X509_get_serialNumber(pCert);

                        valLen = asn->length;

                        if(valLen > pTemplate[i].ulValueLen) valLen = pTemplate[i].ulValueLen;

                        TINYCLR_SSL_MEMCPY(pTemplate[i].pValue, asn->data, valLen);
                    }
                    break;

                case CKA_MECHANISM_TYPE:
                    if(pCert->sig_alg != NULL)
                    {
                        int signature_nid;
                        CK_MECHANISM_TYPE type = CKM_VENDOR_DEFINED;
                        
                        signature_nid = OBJ_obj2nid(pCert->sig_alg->algorithm);

                        switch(signature_nid)
                        {
                            case NID_sha1WithRSA:
                            case NID_sha1WithRSAEncryption:
                                //szNid = "1.2.840.113549.1.1.5";
                                type = CKM_SHA1_RSA_PKCS;
                                break;

                            case NID_md5WithRSA:
                            case NID_md5WithRSAEncryption:
                                //szNid = "1.2.840.113549.1.1.4";
                                type = CKM_MD5_RSA_PKCS;
                                break;

                            case NID_sha256WithRSAEncryption:
                                //szNid = "1.2.840.113549.1.1.11";
                                type = CKM_SHA256_RSA_PKCS;
                                break;

                            case NID_sha384WithRSAEncryption:
                                //szNid = "1.2.840.113549.1.1.12";
                                type = CKM_SHA384_RSA_PKCS;
                                break;

                            case NID_sha512WithRSAEncryption:
                                //szNid = "1.2.840.113549.1.1.13";
                                type = CKM_SHA512_RSA_PKCS;
                                break;
                        }

                        valLen = sizeof(CK_MECHANISM_TYPE);
                        *(CK_MECHANISM_TYPE*)pTemplate[i].pValue = SwapEndianIfBEc32(type);
                    }
                    break;

                case CKA_START_DATE:
                    {
                        DATE_TIME_INFO dti;
                        
                        ssl_get_ASN1_UTCTIME(X509_get_notBefore(pCert), &dti);

                        valLen = (INT32)pTemplate[i].ulValueLen;

                        if(valLen > sizeof(dti)) valLen = sizeof(dti);

                        TINYCLR_SSL_MEMCPY(pTemplate[i].pValue, &dti, valLen);
                    }
                    break;

                case CKA_END_DATE:
                    {
                        DATE_TIME_INFO dti;
                        
                        ssl_get_ASN1_UTCTIME(X509_get_notAfter(pCert), &dti);

                        valLen = pTemplate[i].ulValueLen;

                        if(valLen > sizeof(dti)) valLen = sizeof(dti);

                        TINYCLR_SSL_MEMCPY(pTemplate[i].pValue, &dti, valLen);
                    }
                    break;

                case CKA_VALUE:
                    {
                        UINT8* pData = (UINT8*)pTemplate[i].pValue;
                        UINT8* pTmp = pData;

                        valLen = i2d_X509(pCert, NULL);

                        if(valLen > pTemplate[i].ulValueLen) return CKR_DEVICE_MEMORY;
                        
                        valLen = i2d_X509(pCert, &pTmp);

                        if(valLen < 0) return CKR_FUNCTION_FAILED;
                    }
                    break;

                case CKA_VALUE_LEN:
                    *(UINT32*)pTemplate[i].pValue = SwapEndianIfBEc32(valLen);
                    break;

                default:
                    return CKR_ATTRIBUTE_TYPE_INVALID;
            }
        }
    }
    else if(pObj->Type == KeyType)
    {
        KEY_DATA* pKey = (KEY_DATA*)pObj->Data;
        int valLen = 0;
        bool isPrivate = false;

        for(int i=0; i<(int)ulCount; i++)
        {
            switch(pTemplate[i].type)
            {
                case CKA_CLASS:
                    *(INT32*)pTemplate[i].pValue = SwapEndianIfBEc32((0 != (pKey->attrib & Private) ? CKO_PRIVATE_KEY : 0 != (pKey->attrib & Public) ? CKO_PUBLIC_KEY : CKO_SECRET_KEY));
                    break;
                    
                case CKA_MODULUS:
                    if(pKey->type == CKK_RSA)
                    {
                        EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key;

                        valLen = BN_bn2bin(pRealKey->pkey.rsa->n, (UINT8*)pTemplate[i].pValue);
                    }    
                    break;

                case CKA_EXPONENT_1:
                    if(pKey->type == CKK_RSA)
                    {
                        EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key;

                        valLen = BN_bn2bin(pRealKey->pkey.rsa->dmp1, (UINT8*)pTemplate[i].pValue);
                    }    
                    break;

                case CKA_EXPONENT_2:
                    if(pKey->type == CKK_RSA)
                    {
                        EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key;

                        valLen = BN_bn2bin(pRealKey->pkey.rsa->dmq1, (UINT8*)pTemplate[i].pValue);
                    }    
                    break;

                case CKA_COEFFICIENT:
                    if(pKey->type == CKK_RSA)
                    {
                        EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key;

                        valLen = BN_bn2bin(pRealKey->pkey.rsa->iqmp, (UINT8*)pTemplate[i].pValue);
                    }    
                    break;
                    
                case CKA_PRIME_1:
                    if(pKey->type == CKK_RSA)
                    {
                        EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key;

                        valLen = BN_bn2bin(pRealKey->pkey.rsa->p, (UINT8*)pTemplate[i].pValue);
                    }    
                    break;

                case CKA_PRIME_2:
                    if(pKey->type == CKK_RSA)
                    {
                        EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key;

                        valLen = BN_bn2bin(pRealKey->pkey.rsa->q, (UINT8*)pTemplate[i].pValue);
                    }    
                    break;

                
                case CKA_PRIVATE_EXPONENT:
                    if(pKey->type == CKK_DSA)
                    {
                        EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key;

                        valLen = BN_bn2bin(pRealKey->pkey.dsa->priv_key, (UINT8*)pTemplate[i].pValue);
                    }
                    else if(pKey->type == CKK_RSA)
                    {
                        EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key;

                        valLen = BN_bn2bin(pRealKey->pkey.rsa->d, (UINT8*)pTemplate[i].pValue);
                    }
                    break;
                case CKA_PUBLIC_EXPONENT:
                    if(pKey->type == CKK_DSA)
                    {
                        EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key;
                
                        valLen = BN_bn2bin(pRealKey->pkey.dsa->pub_key, (UINT8*)pTemplate[i].pValue);
                    }
                    else if(pKey->type == CKK_EC)
                    {
                        UINT8 pTmp[66*2+1];
                    
                        EC_KEY* pEC = ((EVP_PKEY*)pKey->key)->pkey.ec;
                        
                        const EC_POINT* point = EC_KEY_get0_public_key(pEC);
                        valLen = EC_POINT_point2oct(EC_KEY_get0_group(pEC), point, POINT_CONVERSION_UNCOMPRESSED, (UINT8*)pTmp, ARRAYSIZE(pTmp), NULL);
                    
                        if(valLen == 0) return CKR_FUNCTION_FAILED;
                            
                        memmove(pTemplate[i].pValue, &pTmp[1], valLen-1); // remove POINT_CONVERSION_UNCOMPRESSED header byte
                    }
                    else if(pKey->type == CKK_RSA)
                    {
                        EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key;

                        valLen = BN_bn2bin(pRealKey->pkey.rsa->e, (UINT8*)pTemplate[i].pValue);
                    }                    
                    break;

                case CKA_PRIME:
                    if(pKey->type == CKK_DSA)
                    {
                        EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key;

                        valLen = BN_bn2bin(pRealKey->pkey.dsa->p, (UINT8*)pTemplate[i].pValue);
                    }
                    break;

                case CKA_SUBPRIME:
                    if(pKey->type == CKK_DSA)
                    {
                        EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key;

                        valLen = BN_bn2bin(pRealKey->pkey.dsa->q, (UINT8*)pTemplate[i].pValue);
                    }
                    break;

                case CKA_BASE:
                    if(pKey->type == CKK_DSA)
                    {
                        EVP_PKEY* pRealKey = (EVP_PKEY*)pKey->key;
                        
                        valLen = BN_bn2bin(pRealKey->pkey.dsa->g, (UINT8*)pTemplate[i].pValue);
                    }
                    break;

                case CKA_PRIVATE:
                    isPrivate = 0 != *(INT32*)pTemplate[i].pValue;
                    break;
                

                case CKA_KEY_TYPE:
                    *(INT32*)pTemplate[i].pValue = SwapEndianIfBEc32(pKey->type);
                    break; 

                case CKA_VALUE_BITS:
                    *(UINT32*)pTemplate[i].pValue = SwapEndianIfBEc32(pKey->size);
                    break;

                case CKA_VALUE:
                    switch(pKey->type)
                    {
                        case CKK_AES:
                        case CKK_GENERIC_SECRET:
                            {
                                // TODO: Add permissions to export key
                                int len = (pKey->size + 7) / 8;
                                
                                if(len > (INT32)pTemplate[i].ulValueLen) len = (int)pTemplate[i].ulValueLen;
                                
                                TINYCLR_SSL_MEMCPY(pTemplate[i].pValue, pKey->key, len);
                                valLen = len;
                            }
                            break;

                        default:
                            return CKR_ATTRIBUTE_TYPE_INVALID;                                
                    }
                    break;

                case CKA_VALUE_LEN:
                    switch(pKey->type)
                    {
                        case CKK_EC:
                            *(UINT32*)pTemplate[i].pValue = SwapEndianIfBEc32(valLen);
                            break;

                        default:
                            return CKR_ATTRIBUTE_TYPE_INVALID;
                    }
                    break;

                default:
                    return CKR_ATTRIBUTE_TYPE_INVALID;
            }
        }
    }

    return CKR_OK;    
}
/* read the data and then respond */
static int client_certificate(SSL *s)
	{
	unsigned char *buf;
	unsigned char *p,*d;
	int i;
	unsigned int n;
	int cert_ch_len;
	unsigned char *cert_ch;

	buf=(unsigned char *)s->init_buf->data;

	/* We have a cert associated with the SSL, so attach it to
	 * the session if it does not have one */

	if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_A)
		{
		i=ssl2_read(s,(char *)&(buf[s->init_num]),
			SSL2_MAX_CERT_CHALLENGE_LENGTH+2-s->init_num);
		if (i<(SSL2_MIN_CERT_CHALLENGE_LENGTH+2-s->init_num))
			return(ssl2_part_read(s,SSL_F_CLIENT_CERTIFICATE,i));
		s->init_num += i;
		if (s->msg_callback)
			s->msg_callback(0, s->version, 0, buf, (size_t)s->init_num, s, s->msg_callback_arg); /* REQUEST-CERTIFICATE */

		/* type=buf[0]; */
		/* type eq x509 */
		if (buf[1] != SSL2_AT_MD5_WITH_RSA_ENCRYPTION)
			{
			ssl2_return_error(s,SSL2_PE_UNSUPPORTED_CERTIFICATE_TYPE);
			SSLerr(SSL_F_CLIENT_CERTIFICATE,SSL_R_BAD_AUTHENTICATION_TYPE);
			return(-1);
			}

		if ((s->cert == NULL) ||
			(s->cert->key->x509 == NULL) ||
			(s->cert->key->privatekey == NULL))
			{
			s->state=SSL2_ST_X509_GET_CLIENT_CERTIFICATE;
			}
		else
			s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_C;
		}

	cert_ch = buf + 2;
	cert_ch_len = s->init_num - 2;

	if (s->state == SSL2_ST_X509_GET_CLIENT_CERTIFICATE)
		{
		X509 *x509=NULL;
		EVP_PKEY *pkey=NULL;

		/* If we get an error we need to
		 * ssl->rwstate=SSL_X509_LOOKUP;
		 * return(error);
		 * We should then be retried when things are ok and we
		 * can get a cert or not */

		i=0;
		if (s->ctx->client_cert_cb != NULL)
			{
			i=s->ctx->client_cert_cb(s,&(x509),&(pkey));
			}

		if (i < 0)
			{
			s->rwstate=SSL_X509_LOOKUP;
			return(-1);
			}
		s->rwstate=SSL_NOTHING;

		if ((i == 1) && (pkey != NULL) && (x509 != NULL))
			{
			s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_C;
			if (	!SSL_use_certificate(s,x509) || 
				!SSL_use_PrivateKey(s,pkey))
				{
				i=0;
				}
			X509_free(x509);
			EVP_PKEY_free(pkey);
			}
		else if (i == 1)
			{
			if (x509 != NULL) X509_free(x509);
			if (pkey != NULL) EVP_PKEY_free(pkey);
			SSLerr(SSL_F_CLIENT_CERTIFICATE,SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
			i=0;
			}

		if (i == 0)
			{
			/* We have no client certificate to respond with
			 * so send the correct error message back */
			s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_B;
			p=buf;
			*(p++)=SSL2_MT_ERROR;
			s2n(SSL2_PE_NO_CERTIFICATE,p);
			s->init_off=0;
			s->init_num=3;
			/* Write is done at the end */
			}
		}

	if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_B)
		{
		return(ssl2_do_write(s));
		}

	if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_C)
		{
		EVP_MD_CTX ctx;

		/* ok, now we calculate the checksum
		 * do it first so we can reuse buf :-) */
		p=buf;
		EVP_MD_CTX_init(&ctx);
		EVP_SignInit_ex(&ctx,s->ctx->rsa_md5, NULL);
		EVP_SignUpdate(&ctx,s->s2->key_material,
			       s->s2->key_material_length);
		EVP_SignUpdate(&ctx,cert_ch,(unsigned int)cert_ch_len);
		i=i2d_X509(s->session->sess_cert->peer_key->x509,&p);
		/* Don't update the signature if it fails - FIXME: probably should handle this better */
		if(i > 0)
			EVP_SignUpdate(&ctx,buf,(unsigned int)i);

		p=buf;
		d=p+6;
		*(p++)=SSL2_MT_CLIENT_CERTIFICATE;
		*(p++)=SSL2_CT_X509_CERTIFICATE;
		n=i2d_X509(s->cert->key->x509,&d);
		s2n(n,p);

		if (!EVP_SignFinal(&ctx,d,&n,s->cert->key->privatekey))
			{
			/* this is not good.  If things have failed it
			 * means there so something wrong with the key.
			 * We will continue with a 0 length signature
			 */
			}
		EVP_MD_CTX_cleanup(&ctx);
		s2n(n,p);
		d+=n;

		s->state=SSL2_ST_SEND_CLIENT_CERTIFICATE_D;
		s->init_num=d-buf;
		s->init_off=0;
		}
	/* if (s->state == SSL2_ST_SEND_CLIENT_CERTIFICATE_D) */
	return(ssl2_do_write(s));
	}
CK_RV PKCS11_Objects_OpenSSL::SetAttributeValue(Cryptoki_Session_Context* pSessionCtx, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) 
{
    OBJECT_DATA* pObj = PKCS11_Objects_OpenSSL::GetObjectFromHandle(pSessionCtx, hObject);

    if(pObj == NULL) return CKR_OBJECT_HANDLE_INVALID;

    if(pObj->Type == CertificateType)
    {
        CERT_DATA* pCertData = (CERT_DATA*)pObj->Data;
        X509* pCert = pCertData->cert;
        CHAR group[20] = {0};
        CHAR fileName[20] = {0};
        INT32 len = 0;

        BOOL fSave = FALSE;
        BOOL fDelete = FALSE;
    
        for(int i=0; i<(int)ulCount; i++)
        {
            switch(pTemplate[i].type)
            {
                case CKA_PERSIST:
                    fSave = SwapEndianIfBEc32(*(INT32*)pTemplate[i].pValue) != 0;
                    fDelete = !fSave;
                    break;

                case CKA_LABEL:
                    len = pTemplate[i].ulValueLen;

                    if(len >= ARRAYSIZE(group))
                    {
                        len = ARRAYSIZE(group) - 1;
                    }
                    
                    TINYCLR_SSL_MEMCPY(group, pTemplate[i].pValue, len);
                    
                    group[len] = 0;
                    
                    break;

                case CKA_OBJECT_ID:
                    len = pTemplate[i].ulValueLen;

                    if(len >= ARRAYSIZE(fileName))
                    {
                        len = ARRAYSIZE(fileName) - 1;
                    }
                    
                    TINYCLR_SSL_MEMCPY(fileName, pTemplate[i].pValue, len);
                    
                    fileName[len] = 0;
                    
                    break;

                default:
                    return CKR_ATTRIBUTE_TYPE_INVALID;
            }
        }

        if(fDelete)
        {
            hal_strcpy_s(fileName, ARRAYSIZE(pObj->FileName), pObj->FileName);

            pObj->GroupName[0] = 0;
                
            if(g_OpenSSL_Token.Storage != NULL && g_OpenSSL_Token.Storage->Delete != NULL)
            {
                if(!g_OpenSSL_Token.Storage->Delete(fileName, group)) return CKR_FUNCTION_FAILED;
            }
            else
            {
                return CKR_FUNCTION_NOT_SUPPORTED;
            }
        }
        else if(fSave)
        {
            hal_strcpy_s(pObj->GroupName, ARRAYSIZE(pObj->GroupName), group   );
            hal_strcpy_s(pObj->FileName , ARRAYSIZE(pObj->FileName ), fileName);
            
            if(g_OpenSSL_Token.Storage != NULL && g_OpenSSL_Token.Storage->Create != NULL)
            {
                BOOL res;
                UINT8* pData, *pTmp;
                INT32 len = i2d_X509( pCert, NULL );

                if(len <= 0) return CKR_FUNCTION_FAILED;

                pData = (UINT8*)TINYCLR_SSL_MALLOC(len);

                if(pData == NULL) return CKR_DEVICE_MEMORY;

                pTmp = pData;

                i2d_X509(pCert, &pTmp);

                // TODO: Save private key as well
                
                res = g_OpenSSL_Token.Storage->Create( fileName, group, CertificateType, pData, len );

                TINYCLR_SSL_FREE(pData);

                if(!res) return CKR_FUNCTION_FAILED;
            }
            else
            {
                return CKR_FUNCTION_NOT_SUPPORTED;
            }
        }
        else
        {
            return CKR_ATTRIBUTE_TYPE_INVALID;
        }
    }

    return CKR_OK;
}
示例#22
0
extern "C" int32_t GetX509DerSize(X509* x)
{
    return i2d_X509(x, nullptr);
}
示例#23
0
unsigned long dtls1_output_cert_chain(SSL *s, X509 *x)
	{
	unsigned char *p;
	int n,i;
	unsigned long l= 3 + DTLS1_HM_HEADER_LENGTH;
	BUF_MEM *buf;
	X509_STORE_CTX xs_ctx;
	X509_OBJECT obj;

	/* TLSv1 sends a chain with nothing in it, instead of an alert */
	buf=s->init_buf;
	if (!BUF_MEM_grow_clean(buf,10))
		{
		SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
		return(0);
		}
	if (x != NULL)
		{
		if(!X509_STORE_CTX_init(&xs_ctx,s->ctx->cert_store,NULL,NULL))
			{
			SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_X509_LIB);
			return(0);
			}

		for (;;)
			{
			n=i2d_X509(x,NULL);
			if (!BUF_MEM_grow_clean(buf,(int)(n+l+3)))
				{
				SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
				return(0);
				}
			p=(unsigned char *)&(buf->data[l]);
			l2n3(n,p);
			i2d_X509(x,&p);
			l+=n+3;
			if (X509_NAME_cmp(X509_get_subject_name(x),
				X509_get_issuer_name(x)) == 0) break;

			i=X509_STORE_get_by_subject(&xs_ctx,X509_LU_X509,
				X509_get_issuer_name(x),&obj);
			if (i <= 0) break;
			x=obj.data.x509;
			/* Count is one too high since the X509_STORE_get uped the
			 * ref count */
			X509_free(x);
			}

		X509_STORE_CTX_cleanup(&xs_ctx);
		}

	/* Thawte special :-) */
	if (s->ctx->extra_certs != NULL)
	for (i=0; i<sk_X509_num(s->ctx->extra_certs); i++)
		{
		x=sk_X509_value(s->ctx->extra_certs,i);
		n=i2d_X509(x,NULL);
		if (!BUF_MEM_grow_clean(buf,(int)(n+l+3)))
			{
			SSLerr(SSL_F_DTLS1_OUTPUT_CERT_CHAIN,ERR_R_BUF_LIB);
			return(0);
			}
		p=(unsigned char *)&(buf->data[l]);
		l2n3(n,p);
		i2d_X509(x,&p);
		l+=n+3;
		}

	l-= (3 + DTLS1_HM_HEADER_LENGTH);

	p=(unsigned char *)&(buf->data[DTLS1_HM_HEADER_LENGTH]);
	l2n3(l,p);
	l+=3;
	p=(unsigned char *)&(buf->data[0]);
	p = dtls1_set_message_header(s, p, SSL3_MT_CERTIFICATE, l, 0, l);

	l+=DTLS1_HM_HEADER_LENGTH;
	return(l);
	}
示例#24
0
int MAIN(int argc, char **argv)
	{
	ENGINE *e = NULL;
	int ret=1;
	X509_REQ *req=NULL;
	X509 *x=NULL,*xca=NULL;
	ASN1_OBJECT *objtmp;
	EVP_PKEY *Upkey=NULL,*CApkey=NULL;
	ASN1_INTEGER *sno = NULL;
	int i,num,badops=0;
	BIO *out=NULL;
	BIO *STDout=NULL;
	STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
	int informat,outformat,keyformat,CAformat,CAkeyformat;
	char *infile=NULL,*outfile=NULL,*keyfile=NULL,*CAfile=NULL;
	char *CAkeyfile=NULL,*CAserial=NULL;
	char *alias=NULL;
	int text=0,serial=0,subject=0,issuer=0,startdate=0,enddate=0;
	int next_serial=0;
	int subject_hash=0,issuer_hash=0,ocspid=0;
	int noout=0,sign_flag=0,CA_flag=0,CA_createserial=0,email=0;
	int ocsp_uri=0;
	int trustout=0,clrtrust=0,clrreject=0,aliasout=0,clrext=0;
	int C=0;
	int x509req=0,days=DEF_DAYS,modulus=0,pubkey=0;
	int pprint = 0;
	const char **pp;
	X509_STORE *ctx=NULL;
	X509_REQ *rq=NULL;
	int fingerprint=0;
	char buf[256];
	const EVP_MD *md_alg,*digest=EVP_sha1();
	CONF *extconf = NULL;
	char *extsect = NULL, *extfile = NULL, *passin = NULL, *passargin = NULL;
	int need_rand = 0;
	int checkend=0,checkoffset=0;
	unsigned long nmflag = 0, certflag = 0;
#ifndef OPENSSL_NO_ENGINE
	char *engine=NULL;
#endif

	reqfile=0;

	apps_startup();

	if (bio_err == NULL)
		bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);

	if (!load_config(bio_err, NULL))
		goto end;
	STDout=BIO_new_fp(stdout,BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
	{
	BIO *tmpbio = BIO_new(BIO_f_linebuffer());
	STDout = BIO_push(tmpbio, STDout);
	}
#endif

	informat=FORMAT_PEM;
	outformat=FORMAT_PEM;
	keyformat=FORMAT_PEM;
	CAformat=FORMAT_PEM;
	CAkeyformat=FORMAT_PEM;

	ctx=X509_STORE_new();
	if (ctx == NULL) goto end;
	X509_STORE_set_verify_cb_func(ctx,callb);

	argc--;
	argv++;
	num=0;
	while (argc >= 1)
		{
		if 	(strcmp(*argv,"-inform") == 0)
			{
			if (--argc < 1) goto bad;
			informat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-outform") == 0)
			{
			if (--argc < 1) goto bad;
			outformat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-keyform") == 0)
			{
			if (--argc < 1) goto bad;
			keyformat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-req") == 0)
			{
			reqfile=1;
			need_rand = 1;
			}
		else if (strcmp(*argv,"-CAform") == 0)
			{
			if (--argc < 1) goto bad;
			CAformat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-CAkeyform") == 0)
			{
			if (--argc < 1) goto bad;
			CAkeyformat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-days") == 0)
			{
			if (--argc < 1) goto bad;
			days=atoi(*(++argv));
			if (days == 0)
				{
				BIO_printf(STDout,"bad number of days\n");
				goto bad;
				}
			}
		else if (strcmp(*argv,"-passin") == 0)
			{
			if (--argc < 1) goto bad;
			passargin= *(++argv);
			}
		else if (strcmp(*argv,"-extfile") == 0)
			{
			if (--argc < 1) goto bad;
			extfile= *(++argv);
			}
		else if (strcmp(*argv,"-extensions") == 0)
			{
			if (--argc < 1) goto bad;
			extsect= *(++argv);
			}
		else if (strcmp(*argv,"-in") == 0)
			{
			if (--argc < 1) goto bad;
			infile= *(++argv);
			}
		else if (strcmp(*argv,"-out") == 0)
			{
			if (--argc < 1) goto bad;
			outfile= *(++argv);
			}
		else if (strcmp(*argv,"-signkey") == 0)
			{
			if (--argc < 1) goto bad;
			keyfile= *(++argv);
			sign_flag= ++num;
			need_rand = 1;
			}
		else if (strcmp(*argv,"-CA") == 0)
			{
			if (--argc < 1) goto bad;
			CAfile= *(++argv);
			CA_flag= ++num;
			need_rand = 1;
			}
		else if (strcmp(*argv,"-CAkey") == 0)
			{
			if (--argc < 1) goto bad;
			CAkeyfile= *(++argv);
			}
		else if (strcmp(*argv,"-CAserial") == 0)
			{
			if (--argc < 1) goto bad;
			CAserial= *(++argv);
			}
		else if (strcmp(*argv,"-set_serial") == 0)
			{
			if (--argc < 1) goto bad;
			if (!(sno = s2i_ASN1_INTEGER(NULL, *(++argv))))
				goto bad;
			}
		else if (strcmp(*argv,"-addtrust") == 0)
			{
			if (--argc < 1) goto bad;
			if (!(objtmp = OBJ_txt2obj(*(++argv), 0)))
				{
				BIO_printf(bio_err,
					"Invalid trust object value %s\n", *argv);
				goto bad;
				}
			if (!trust) trust = sk_ASN1_OBJECT_new_null();
			sk_ASN1_OBJECT_push(trust, objtmp);
			trustout = 1;
			}
		else if (strcmp(*argv,"-addreject") == 0)
			{
			if (--argc < 1) goto bad;
			if (!(objtmp = OBJ_txt2obj(*(++argv), 0)))
				{
				BIO_printf(bio_err,
					"Invalid reject object value %s\n", *argv);
				goto bad;
				}
			if (!reject) reject = sk_ASN1_OBJECT_new_null();
			sk_ASN1_OBJECT_push(reject, objtmp);
			trustout = 1;
			}
		else if (strcmp(*argv,"-setalias") == 0)
			{
			if (--argc < 1) goto bad;
			alias= *(++argv);
			trustout = 1;
			}
		else if (strcmp(*argv,"-certopt") == 0)
			{
			if (--argc < 1) goto bad;
			if (!set_cert_ex(&certflag, *(++argv))) goto bad;
			}
		else if (strcmp(*argv,"-nameopt") == 0)
			{
			if (--argc < 1) goto bad;
			if (!set_name_ex(&nmflag, *(++argv))) goto bad;
			}
#ifndef OPENSSL_NO_ENGINE
		else if (strcmp(*argv,"-engine") == 0)
			{
			if (--argc < 1) goto bad;
			engine= *(++argv);
			}
#endif
		else if (strcmp(*argv,"-C") == 0)
			C= ++num;
		else if (strcmp(*argv,"-email") == 0)
			email= ++num;
		else if (strcmp(*argv,"-ocsp_uri") == 0)
			ocsp_uri= ++num;
		else if (strcmp(*argv,"-serial") == 0)
			serial= ++num;
		else if (strcmp(*argv,"-next_serial") == 0)
			next_serial= ++num;
		else if (strcmp(*argv,"-modulus") == 0)
			modulus= ++num;
		else if (strcmp(*argv,"-pubkey") == 0)
			pubkey= ++num;
		else if (strcmp(*argv,"-x509toreq") == 0)
			x509req= ++num;
		else if (strcmp(*argv,"-text") == 0)
			text= ++num;
		else if (strcmp(*argv,"-hash") == 0
			|| strcmp(*argv,"-subject_hash") == 0)
			subject_hash= ++num;
		else if (strcmp(*argv,"-issuer_hash") == 0)
			issuer_hash= ++num;
		else if (strcmp(*argv,"-subject") == 0)
			subject= ++num;
		else if (strcmp(*argv,"-issuer") == 0)
			issuer= ++num;
		else if (strcmp(*argv,"-fingerprint") == 0)
			fingerprint= ++num;
		else if (strcmp(*argv,"-dates") == 0)
			{
			startdate= ++num;
			enddate= ++num;
			}
		else if (strcmp(*argv,"-purpose") == 0)
			pprint= ++num;
		else if (strcmp(*argv,"-startdate") == 0)
			startdate= ++num;
		else if (strcmp(*argv,"-enddate") == 0)
			enddate= ++num;
		else if (strcmp(*argv,"-checkend") == 0)
			{
			if (--argc < 1) goto bad;
			checkoffset=atoi(*(++argv));
			checkend=1;
			}
		else if (strcmp(*argv,"-noout") == 0)
			noout= ++num;
		else if (strcmp(*argv,"-trustout") == 0)
			trustout= 1;
		else if (strcmp(*argv,"-clrtrust") == 0)
			clrtrust= ++num;
		else if (strcmp(*argv,"-clrreject") == 0)
			clrreject= ++num;
		else if (strcmp(*argv,"-alias") == 0)
			aliasout= ++num;
		else if (strcmp(*argv,"-CAcreateserial") == 0)
			CA_createserial= ++num;
		else if (strcmp(*argv,"-clrext") == 0)
			clrext = 1;
#if 1 /* stay backwards-compatible with 0.9.5; this should go away soon */
		else if (strcmp(*argv,"-crlext") == 0)
			{
			BIO_printf(bio_err,"use -clrext instead of -crlext\n");
			clrext = 1;
			}
#endif
		else if (strcmp(*argv,"-ocspid") == 0)
			ocspid= ++num;
		else if ((md_alg=EVP_get_digestbyname(*argv + 1)))
			{
			/* ok */
			digest=md_alg;
			}
		else
			{
			BIO_printf(bio_err,"unknown option %s\n",*argv);
			badops=1;
			break;
			}
		argc--;
		argv++;
		}

	if (badops)
		{
bad:
		for (pp=x509_usage; (*pp != NULL); pp++)
			BIO_printf(bio_err,"%s",*pp);
		goto end;
		}

#ifndef OPENSSL_NO_ENGINE
        e = setup_engine(bio_err, engine, 0);
#endif

	if (need_rand)
		app_RAND_load_file(NULL, bio_err, 0);

	ERR_load_crypto_strings();

	if (!app_passwd(bio_err, passargin, NULL, &passin, NULL))
		{
		BIO_printf(bio_err, "Error getting password\n");
		goto end;
		}

	if (!X509_STORE_set_default_paths(ctx))
		{
		ERR_print_errors(bio_err);
		goto end;
		}

	if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM))
		{ CAkeyfile=CAfile; }
	else if ((CA_flag) && (CAkeyfile == NULL))
		{
		BIO_printf(bio_err,"need to specify a CAkey if using the CA command\n");
		goto end;
		}

	if (extfile)
		{
		long errorline = -1;
		X509V3_CTX ctx2;
		extconf = NCONF_new(NULL);
		if (!NCONF_load(extconf, extfile,&errorline))
			{
			if (errorline <= 0)
				BIO_printf(bio_err,
					"error loading the config file '%s'\n",
								extfile);
                	else
                        	BIO_printf(bio_err,
				       "error on line %ld of config file '%s'\n"
							,errorline,extfile);
			goto end;
			}
		if (!extsect)
			{
			extsect = NCONF_get_string(extconf, "default", "extensions");
			if (!extsect)
				{
				ERR_clear_error();
				extsect = "default";
				}
			}
		X509V3_set_ctx_test(&ctx2);
		X509V3_set_nconf(&ctx2, extconf);
		if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL))
			{
			BIO_printf(bio_err,
				"Error Loading extension section %s\n",
								 extsect);
			ERR_print_errors(bio_err);
			goto end;
			}
		}


	if (reqfile)
		{
		EVP_PKEY *pkey;
		X509_CINF *ci;
		BIO *in;

		if (!sign_flag && !CA_flag)
			{
			BIO_printf(bio_err,"We need a private key to sign with\n");
			goto end;
			}
		in=BIO_new(BIO_s_file());
		if (in == NULL)
			{
			ERR_print_errors(bio_err);
			goto end;
			}

		if (infile == NULL)
			BIO_set_fp(in,stdin,BIO_NOCLOSE|BIO_FP_TEXT);
		else
			{
			if (BIO_read_filename(in,infile) <= 0)
				{
				perror(infile);
				BIO_free(in);
				goto end;
				}
			}
		req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);
		BIO_free(in);

		if (req == NULL)
			{
			ERR_print_errors(bio_err);
			goto end;
			}

		if (	(req->req_info == NULL) ||
			(req->req_info->pubkey == NULL) ||
			(req->req_info->pubkey->public_key == NULL) ||
			(req->req_info->pubkey->public_key->data == NULL))
			{
			BIO_printf(bio_err,"The certificate request appears to corrupted\n");
			BIO_printf(bio_err,"It does not contain a public key\n");
			goto end;
			}
		if ((pkey=X509_REQ_get_pubkey(req)) == NULL)
	                {
	                BIO_printf(bio_err,"error unpacking public key\n");
	                goto end;
	                }
		i=X509_REQ_verify(req,pkey);
		EVP_PKEY_free(pkey);
		if (i < 0)
			{
			BIO_printf(bio_err,"Signature verification error\n");
			ERR_print_errors(bio_err);
			goto end;
			}
	        if (i == 0)
			{
			BIO_printf(bio_err,"Signature did not match the certificate request\n");
			goto end;
			}
		else
			BIO_printf(bio_err,"Signature ok\n");

		print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), nmflag);

		if ((x=X509_new()) == NULL) goto end;
		ci=x->cert_info;

		if (sno == NULL)
			{
			sno = ASN1_INTEGER_new();
			if (!sno || !rand_serial(NULL, sno))
				goto end;
			if (!X509_set_serialNumber(x, sno)) 
				goto end;
			ASN1_INTEGER_free(sno);
			sno = NULL;
			}
		else if (!X509_set_serialNumber(x, sno)) 
			goto end;

		if (!X509_set_issuer_name(x,req->req_info->subject)) goto end;
		if (!X509_set_subject_name(x,req->req_info->subject)) goto end;

		X509_gmtime_adj(X509_get_notBefore(x),0);
	        X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days);

		pkey = X509_REQ_get_pubkey(req);
		X509_set_pubkey(x,pkey);
		EVP_PKEY_free(pkey);
		}
	else
		x=load_cert(bio_err,infile,informat,NULL,e,"Certificate");

	if (x == NULL) goto end;
	if (CA_flag)
		{
		xca=load_cert(bio_err,CAfile,CAformat,NULL,e,"CA Certificate");
		if (xca == NULL) goto end;
		}

	if (!noout || text || next_serial)
		{
		OBJ_create("2.99999.3",
			"SET.ex3","SET x509v3 extension 3");

		out=BIO_new(BIO_s_file());
		if (out == NULL)
			{
			ERR_print_errors(bio_err);
			goto end;
			}
		if (outfile == NULL)
			{
			BIO_set_fp(out,stdout,BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
			{
			BIO *tmpbio = BIO_new(BIO_f_linebuffer());
			out = BIO_push(tmpbio, out);
			}
#endif
			}
		else
			{
			if (BIO_write_filename(out,outfile) <= 0)
				{
				perror(outfile);
				goto end;
				}
			}
		}

	if (alias) X509_alias_set1(x, (unsigned char *)alias, -1);

	if (clrtrust) X509_trust_clear(x);
	if (clrreject) X509_reject_clear(x);

	if (trust)
		{
		for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++)
			{
			objtmp = sk_ASN1_OBJECT_value(trust, i);
			X509_add1_trust_object(x, objtmp);
			}
		}

	if (reject)
		{
		for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++)
			{
			objtmp = sk_ASN1_OBJECT_value(reject, i);
			X509_add1_reject_object(x, objtmp);
			}
		}

	if (num)
		{
		for (i=1; i<=num; i++)
			{
			if (issuer == i)
				{
				print_name(STDout, "issuer= ",
					X509_get_issuer_name(x), nmflag);
				}
			else if (subject == i) 
				{
				print_name(STDout, "subject= ",
					X509_get_subject_name(x), nmflag);
				}
			else if (serial == i)
				{
				BIO_printf(STDout,"serial=");
				i2a_ASN1_INTEGER(STDout,
					X509_get_serialNumber(x));
				BIO_printf(STDout,"\n");
				}
			else if (next_serial == i)
				{
				BIGNUM *bnser;
				ASN1_INTEGER *ser;
				ser = X509_get_serialNumber(x);
				bnser = ASN1_INTEGER_to_BN(ser, NULL);
				if (!bnser)
					goto end;
				if (!BN_add_word(bnser, 1))
					goto end;
				ser = BN_to_ASN1_INTEGER(bnser, NULL);
				if (!ser)
					goto end;
				BN_free(bnser);
				i2a_ASN1_INTEGER(out, ser);
				ASN1_INTEGER_free(ser);
				BIO_puts(out, "\n");
				}
			else if ((email == i) || (ocsp_uri == i))
				{
				int j;
				STACK *emlst;
				if (email == i)
					emlst = X509_get1_email(x);
				else
					emlst = X509_get1_ocsp(x);
				for (j = 0; j < sk_num(emlst); j++)
					BIO_printf(STDout, "%s\n", sk_value(emlst, j));
				X509_email_free(emlst);
				}
			else if (aliasout == i)
				{
				unsigned char *alstr;
				alstr = X509_alias_get0(x, NULL);
				if (alstr) BIO_printf(STDout,"%s\n", alstr);
				else BIO_puts(STDout,"<No Alias>\n");
				}
			else if (subject_hash == i)
				{
				BIO_printf(STDout,"%08lx\n",X509_subject_name_hash(x));
				}
			else if (issuer_hash == i)
				{
				BIO_printf(STDout,"%08lx\n",X509_issuer_name_hash(x));
				}
			else if (pprint == i)
				{
				X509_PURPOSE *ptmp;
				int j;
				BIO_printf(STDout, "Certificate purposes:\n");
				for (j = 0; j < X509_PURPOSE_get_count(); j++)
					{
					ptmp = X509_PURPOSE_get0(j);
					purpose_print(STDout, x, ptmp);
					}
				}
			else
				if (modulus == i)
				{
				EVP_PKEY *pkey;

				pkey=X509_get_pubkey(x);
				if (pkey == NULL)
					{
					BIO_printf(bio_err,"Modulus=unavailable\n");
					ERR_print_errors(bio_err);
					goto end;
					}
				BIO_printf(STDout,"Modulus=");
#ifndef OPENSSL_NO_RSA
				if (pkey->type == EVP_PKEY_RSA)
					BN_print(STDout,pkey->pkey.rsa->n);
				else
#endif
#ifndef OPENSSL_NO_DSA
				if (pkey->type == EVP_PKEY_DSA)
					BN_print(STDout,pkey->pkey.dsa->pub_key);
				else
#endif
					BIO_printf(STDout,"Wrong Algorithm type");
				BIO_printf(STDout,"\n");
				EVP_PKEY_free(pkey);
				}
			else
				if (pubkey == i)
				{
				EVP_PKEY *pkey;

				pkey=X509_get_pubkey(x);
				if (pkey == NULL)
					{
					BIO_printf(bio_err,"Error getting public key\n");
					ERR_print_errors(bio_err);
					goto end;
					}
				PEM_write_bio_PUBKEY(STDout, pkey);
				EVP_PKEY_free(pkey);
				}
			else
				if (C == i)
				{
				unsigned char *d;
				char *m;
				int y,z;

				X509_NAME_oneline(X509_get_subject_name(x),
					buf,sizeof buf);
				BIO_printf(STDout,"/* subject:%s */\n",buf);
				m=X509_NAME_oneline(
					X509_get_issuer_name(x),buf,
					sizeof buf);
				BIO_printf(STDout,"/* issuer :%s */\n",buf);

				z=i2d_X509(x,NULL);
				m=OPENSSL_malloc(z);

				d=(unsigned char *)m;
				z=i2d_X509_NAME(X509_get_subject_name(x),&d);
				BIO_printf(STDout,"unsigned char XXX_subject_name[%d]={\n",z);
				d=(unsigned char *)m;
				for (y=0; y<z; y++)
					{
					BIO_printf(STDout,"0x%02X,",d[y]);
					if ((y & 0x0f) == 0x0f) BIO_printf(STDout,"\n");
					}
				if (y%16 != 0) BIO_printf(STDout,"\n");
				BIO_printf(STDout,"};\n");

				z=i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x),&d);
				BIO_printf(STDout,"unsigned char XXX_public_key[%d]={\n",z);
				d=(unsigned char *)m;
				for (y=0; y<z; y++)
					{
					BIO_printf(STDout,"0x%02X,",d[y]);
					if ((y & 0x0f) == 0x0f)
						BIO_printf(STDout,"\n");
					}
				if (y%16 != 0) BIO_printf(STDout,"\n");
				BIO_printf(STDout,"};\n");

				z=i2d_X509(x,&d);
				BIO_printf(STDout,"unsigned char XXX_certificate[%d]={\n",z);
				d=(unsigned char *)m;
				for (y=0; y<z; y++)
					{
					BIO_printf(STDout,"0x%02X,",d[y]);
					if ((y & 0x0f) == 0x0f)
						BIO_printf(STDout,"\n");
					}
				if (y%16 != 0) BIO_printf(STDout,"\n");
				BIO_printf(STDout,"};\n");

				OPENSSL_free(m);
				}
			else if (text == i)
				{
				X509_print_ex(out,x,nmflag, certflag);
				}
			else if (startdate == i)
				{
				BIO_puts(STDout,"notBefore=");
				ASN1_TIME_print(STDout,X509_get_notBefore(x));
				BIO_puts(STDout,"\n");
				}
			else if (enddate == i)
				{
				BIO_puts(STDout,"notAfter=");
				ASN1_TIME_print(STDout,X509_get_notAfter(x));
				BIO_puts(STDout,"\n");
				}
			else if (fingerprint == i)
				{
				int j;
				unsigned int n;
				unsigned char md[EVP_MAX_MD_SIZE];

				if (!X509_digest(x,digest,md,&n))
					{
					BIO_printf(bio_err,"out of memory\n");
					goto end;
					}
				BIO_printf(STDout,"%s Fingerprint=",
						OBJ_nid2sn(EVP_MD_type(digest)));
				for (j=0; j<(int)n; j++)
					{
					BIO_printf(STDout,"%02X%c",md[j],
						(j+1 == (int)n)
						?'\n':':');
					}
				}

			/* should be in the library */
			else if ((sign_flag == i) && (x509req == 0))
				{
				BIO_printf(bio_err,"Getting Private key\n");
				if (Upkey == NULL)
					{
					Upkey=load_key(bio_err,
						keyfile, keyformat, 0,
						passin, e, "Private key");
					if (Upkey == NULL) goto end;
					}
#ifndef OPENSSL_NO_DSA
		                if (Upkey->type == EVP_PKEY_DSA)
		                        digest=EVP_dss1();
#endif
#ifndef OPENSSL_NO_ECDSA
				if (Upkey->type == EVP_PKEY_EC)
					digest=EVP_ecdsa();
#endif

				assert(need_rand);
				if (!sign(x,Upkey,days,clrext,digest,
						 extconf, extsect)) goto end;
				}
			else if (CA_flag == i)
				{
				BIO_printf(bio_err,"Getting CA Private Key\n");
				if (CAkeyfile != NULL)
					{
					CApkey=load_key(bio_err,
						CAkeyfile, CAkeyformat,
						0, passin, e,
						"CA Private Key");
					if (CApkey == NULL) goto end;
					}
#ifndef OPENSSL_NO_DSA
		                if (CApkey->type == EVP_PKEY_DSA)
		                        digest=EVP_dss1();
#endif
#ifndef OPENSSL_NO_ECDSA
				if (CApkey->type == EVP_PKEY_EC)
					digest = EVP_ecdsa();
#endif
				
				assert(need_rand);
				if (!x509_certify(ctx,CAfile,digest,x,xca,
					CApkey, CAserial,CA_createserial,days, clrext,
					extconf, extsect, sno))
					goto end;
				}
			else if (x509req == i)
				{
				EVP_PKEY *pk;

				BIO_printf(bio_err,"Getting request Private Key\n");
				if (keyfile == NULL)
					{
					BIO_printf(bio_err,"no request key file specified\n");
					goto end;
					}
				else
					{
					pk=load_key(bio_err,
						keyfile, FORMAT_PEM, 0,
						passin, e, "request key");
					if (pk == NULL) goto end;
					}

				BIO_printf(bio_err,"Generating certificate request\n");

#ifndef OPENSSL_NO_DSA
		                if (pk->type == EVP_PKEY_DSA)
		                        digest=EVP_dss1();
#endif
#ifndef OPENSSL_NO_ECDSA
				if (pk->type == EVP_PKEY_EC)
					digest=EVP_ecdsa();
#endif

				rq=X509_to_X509_REQ(x,pk,digest);
				EVP_PKEY_free(pk);
				if (rq == NULL)
					{
					ERR_print_errors(bio_err);
					goto end;
					}
				if (!noout)
					{
					X509_REQ_print(out,rq);
					PEM_write_bio_X509_REQ(out,rq);
					}
				noout=1;
				}
			else if (ocspid == i)
				{
				X509_ocspid_print(out, x);
				}
			}
		}

	if (checkend)
		{
		time_t tcheck=time(NULL) + checkoffset;

		if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0)
			{
			BIO_printf(out,"Certificate will expire\n");
			ret=1;
			}
		else
			{
			BIO_printf(out,"Certificate will not expire\n");
			ret=0;
			}
		goto end;
		}

	if (noout)
		{
		ret=0;
		goto end;
		}

	if 	(outformat == FORMAT_ASN1)
		i=i2d_X509_bio(out,x);
	else if (outformat == FORMAT_PEM)
		{
		if (trustout) i=PEM_write_bio_X509_AUX(out,x);
		else i=PEM_write_bio_X509(out,x);
		}
	else if (outformat == FORMAT_NETSCAPE)
		{
		ASN1_HEADER ah;
		ASN1_OCTET_STRING os;

		os.data=(unsigned char *)NETSCAPE_CERT_HDR;
		os.length=strlen(NETSCAPE_CERT_HDR);
		ah.header= &os;
		ah.data=(char *)x;
		ah.meth=X509_asn1_meth();

		i=ASN1_i2d_bio_of(ASN1_HEADER,i2d_ASN1_HEADER,out,&ah);
		}
	else	{
		BIO_printf(bio_err,"bad output format specified for outfile\n");
		goto end;
		}
	if (!i)
		{
		BIO_printf(bio_err,"unable to write certificate\n");
		ERR_print_errors(bio_err);
		goto end;
		}
	ret=0;
end:
	if (need_rand)
		app_RAND_write_file(NULL, bio_err);
	OBJ_cleanup();
	NCONF_free(extconf);
	BIO_free_all(out);
	BIO_free_all(STDout);
	X509_STORE_free(ctx);
	X509_REQ_free(req);
	X509_free(x);
	X509_free(xca);
	EVP_PKEY_free(Upkey);
	EVP_PKEY_free(CApkey);
	X509_REQ_free(rq);
	ASN1_INTEGER_free(sno);
	sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
	sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
	if (passin) OPENSSL_free(passin);
	apps_shutdown();
	OPENSSL_EXIT(ret);
	}
示例#25
0
Mineserver::Mineserver(int args, char **argarray)
    :  argv(argarray),
       argc(args),
       m_socketlisten  (0),
       m_saveInterval  (0),
       m_lastSave      (std::time(NULL)),
       m_pvp_enabled   (false),
       m_damage_enabled(false),
       m_only_helmets  (false),
       m_running       (false),
       m_eventBase     (NULL),

       // core modules
       m_config        (new Config()),
       m_screen        (new CliScreen()),
       m_logger        (new Logger()),

       m_plugin        (NULL),
       m_chat          (NULL),
       m_furnaceManager(NULL),
       m_packetHandler (NULL),
       m_inventory     (NULL),
       m_mobs          (NULL)
{
    pthread_mutex_init(&m_validation_mutex,NULL);
    ServerInstance = this;
    InitSignals();

    std::srand((uint32_t)std::time(NULL));
    initPRNG();

    std::string cfg;
    std::vector<std::string> overrides;

    for (int i = 1; i < argc; i++)
    {
        const std::string arg(argv[i]);

        switch (arg[0])
        {
        case '-':   // option
            // we have only '-h' and '--help' now, so just return with help
            printHelp(0);
            throw CoreException();

        case '+':   // override
            overrides.push_back(arg.substr(1));
            break;

        default:    // otherwise, it is config file
            if (!cfg.empty())
                throw CoreException("Only single CONFIG_FILE argument is allowed!");
            cfg = arg;
            break;
        }
    }

    const std::string path_exe = "./";

    // If config file is provided as an argument
    if (!cfg.empty())
    {
        std::cout << "Searching for configuration file..." << std::endl;
        if (fileExists(cfg))
        {
            const std::pair<std::string, std::string> fullpath = pathOfFile(cfg);
            cfg = fullpath.first + PATH_SEPARATOR + fullpath.second;
            this->config()->config_path = fullpath.first;
        }
        else
        {
            std::cout << "Config not found...\n";;
            cfg.clear();
        }
    }

    if (cfg.empty())
    {
        if (fileExists(path_exe + PATH_SEPARATOR + CONFIG_FILE))
        {
            cfg = path_exe + PATH_SEPARATOR + CONFIG_FILE;
            this->config()->config_path = path_exe;
        }
        else
        {
            std::cout << "Config not found\n";
        }
    }

    // load config
    Config &configvar = *this->config();
    if (!configvar.load(cfg))
    {
        throw CoreException("Could not load config!");
    }

    m_plugin = new Plugin();

    LOG2(INFO, "Using config: " + cfg);

    if (overrides.size())
    {
        std::stringstream override_config;
        for (size_t i = 0; i < overrides.size(); i++)
        {
            LOG2(INFO, "Overriden: " + overrides[i]);
            override_config << overrides[i] << ';' << std::endl;
        }
        // override config
        if (!configvar.load(override_config))
            throw CoreException("Error when parsing overrides: maybe you forgot to doublequote string values?");
    }

    memset(&m_listenEvent, 0, sizeof(event));
    initConstants();
    // Write PID to file
    std::ofstream pid_out((config()->sData("system.pid_file")).c_str());
    if (!pid_out.fail())
    {
        pid_out << getpid();
    }
    pid_out.close();




    init_plugin_api();

    if (config()->bData("system.interface.use_cli"))
    {
        // Init our Screen
        screen()->init(VERSION);
    }


    LOG2(INFO, "Welcome to Mineserver v" + VERSION);
    LOG2(INFO, "Using zlib "+std::string(ZLIB_VERSION)+" libevent "+std::string(event_get_version()));

    LOG2(INFO, "Generating RSA key pair for protocol encryption");
    //Protocol encryption
    srand(microTime());
    if((rsa = RSA_generate_key(1024, 17, 0, 0)) == NULL)
    {
        LOG2(INFO, "KEY GENERATION FAILED!");
        exit(1);
    }
    LOG2(INFO, "RSA key pair generated.");

    /* Get ASN.1 format public key */
    x=X509_new();
    pk=EVP_PKEY_new();
    EVP_PKEY_assign_RSA(pk,rsa);
    X509_set_version(x,0);
    X509_set_pubkey(x,pk);

    int len;
    unsigned char *buf;
    buf = NULL;
    len = i2d_X509(x, &buf);

    //Glue + jesus tape, dont ask - Fador
    publicKey = std::string((char *)(buf+28),len-36);
    OPENSSL_free(buf);
    /* END key fetching */

    const std::string temp_nums="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890=-";

    const std::string temp_hex="0123456789abcdef";

    for(int i = 0; i < 4; i++)
    {
        encryptionBytes += (char)(temp_nums[rand()%temp_nums.size()]);
    }

    for(int i = 0; i < 16; i++)
    {
        serverID += (char)(temp_hex[rand()%temp_hex.size()]);
    }

    LOG2(INFO, "ServerID: " + serverID);

    if(!m_config->bData("system.user_validation"))
    {
        serverID = "-";
    }

    MapGen* mapgen = new MapGen();
    MapGen* nethergen = new NetherGen();
    MapGen* heavengen = new HeavenGen();
    MapGen* biomegen = new BiomeGen();
    MapGen* eximgen = new EximGen();
    m_mapGenNames.push_back(mapgen);
    m_mapGenNames.push_back(nethergen);
    m_mapGenNames.push_back(heavengen);
    m_mapGenNames.push_back(biomegen);
    m_mapGenNames.push_back(eximgen);

    m_saveInterval = m_config->iData("map.save_interval");

    m_only_helmets = m_config->bData("system.armour.helmet_strict");
    m_pvp_enabled = m_config->bData("system.pvp.enabled");
    m_damage_enabled = m_config->bData("system.damage.enabled");

    const char* key = "map.storage.nbt.directories"; // Prefix for worlds config
    if (m_config->has(key) && (m_config->type(key) == CONFIG_NODE_LIST))
    {
        std::list<std::string> tmp = m_config->mData(key)->keys();
        int n = 0;
        for (std::list<std::string>::const_iterator it = tmp.begin(); it != tmp.end(); ++it)
        {
            m_map.push_back(new Map());
            Physics* phy = new Physics;
            phy->map = n;

            m_physics.push_back(phy);
            RedstoneSimulation* red = new RedstoneSimulation;
            red->map = n;
            m_redstone.push_back(red);
            int k = m_config->iData((std::string(key) + ".") + (*it));
            if ((uint32_t)k >= m_mapGenNames.size())
            {
                std::ostringstream s;
                s << "Error! Mapgen number " << k << " in config. " << m_mapGenNames.size() << " Mapgens known";
                LOG2(INFO, s.str());
            }
            // WARNING: if k is too big this will be an access error! -- louisdx
            MapGen* m = m_mapGenNames[k];
            m_mapGen.push_back(m);
            n++;
        }
    }
    else
    {
        LOG2(WARNING, "Cannot find map.storage.nbt.directories.*");
    }

    if (m_map.size() == 0)
        throw CoreException("No worlds in Config");

    m_chat           = new Chat;
    m_furnaceManager = new FurnaceManager;
    m_packetHandler  = new PacketHandler;
    m_inventory      = new Inventory(m_config->sData("system.path.data") + '/' + "recipes", ".recipe", "ENABLED_RECIPES.cfg");
    m_mobs           = new Mobs;

} // End Mineserver constructor
示例#26
0
carray * mailstream_low_ssl_get_certificate_chain(mailstream_low * s)
{
#ifdef USE_SSL
    struct mailstream_ssl_data * ssl_data;
    carray * result;
    int skpos;
#ifndef USE_GNUTLS
    STACK_OF(X509) * skx;

    ssl_data = (struct mailstream_ssl_data *) s->data;
    if (!(skx = SSL_get_peer_cert_chain(ssl_data->ssl_conn))) {
        return NULL;
    }

    result = carray_new(4);
    for(skpos = 0 ; skpos < sk_num(skx) ; skpos ++) {
        X509 * x = (X509 *) sk_value(skx, skpos);
        unsigned char * p;
        MMAPString * str;
        int length = i2d_X509(x, NULL);
        str = mmap_string_sized_new(length);
        p = (unsigned char *) str->str;
        str->len = length;
        i2d_X509(x, &p);
        carray_add(result, str, NULL);
    }

    return result;
#else
    gnutls_session session = NULL;
    const gnutls_datum *raw_cert_list;
    unsigned int raw_cert_list_length;

    ssl_data = (struct mailstream_ssl_data *) s->data;

    session = ssl_data->session;
    raw_cert_list = gnutls_certificate_get_peers(session, &raw_cert_list_length);

    if (raw_cert_list && gnutls_certificate_type_get(session) == GNUTLS_CRT_X509) {
        result = carray_new(4);
        for(skpos = 0 ; skpos < raw_cert_list_length ; skpos ++) {
            gnutls_x509_crt cert = NULL;
            if (gnutls_x509_crt_init(&cert) >= 0
                    && gnutls_x509_crt_import(cert, &raw_cert_list[skpos], GNUTLS_X509_FMT_DER) >= 0) {
                size_t cert_size = 0;
                MMAPString * str = NULL;
                unsigned char * p;

                if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, NULL, &cert_size)
                        == GNUTLS_E_SHORT_MEMORY_BUFFER) {
                    str = mmap_string_sized_new(cert_size);
                    p = (unsigned char *) str->str;
                    str->len = cert_size;
                }
                if (str != NULL &&
                        gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, p, &cert_size) >= 0) {
                    carray_add(result, str, NULL);
                } else {
                    return NULL;
                }
                gnutls_x509_crt_deinit(cert);
            }
        }
    }

    return result;

    return NULL;
#endif
#else
    return NULL;
#endif
}
示例#27
0
// Import a newly generated P256 pvt key and a certificate
// to every slot and use the key to sign some data
static void test_import_and_sign_all_10() {

  EVP_PKEY       *evp;
  EC_KEY         *eck;
  const EC_POINT *ecp;
  const BIGNUM   *bn;
  char           pvt[32];
  X509           *cert;
  ASN1_TIME      *tm;
  CK_BYTE        i, j;
  CK_BYTE        some_data[32];

  CK_ULONG    class_k = CKO_PRIVATE_KEY;
  CK_ULONG    class_c = CKO_CERTIFICATE;
  CK_ULONG    kt = CKK_ECDSA;
  CK_BYTE     id = 0;
  CK_BYTE     params[] = {0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07};
  CK_BYTE     sig[64];
  CK_ULONG    recv_len;
  CK_BYTE     value_c[3100];
  CK_ULONG    cert_len;
  CK_BYTE     der_encoded[80];
  CK_BYTE_PTR der_ptr;
  CK_BYTE_PTR r_ptr;
  CK_BYTE_PTR s_ptr;
  CK_ULONG    r_len;
  CK_ULONG    s_len;

  unsigned char  *p;

  CK_ATTRIBUTE privateKeyTemplate[] = {
    {CKA_CLASS, &class_k, sizeof(class_k)},
    {CKA_KEY_TYPE, &kt, sizeof(kt)},
    {CKA_ID, &id, sizeof(id)},
    {CKA_EC_PARAMS, &params, sizeof(params)},
    {CKA_VALUE, pvt, sizeof(pvt)}
  };

  CK_ATTRIBUTE publicKeyTemplate[] = {
    {CKA_CLASS, &class_c, sizeof(class_c)},
    {CKA_ID, &id, sizeof(id)},
    {CKA_VALUE, value_c, sizeof(value_c)}
  };

  CK_OBJECT_HANDLE obj[24];
  CK_SESSION_HANDLE session;
  CK_MECHANISM mech = {CKM_ECDSA, NULL};

  evp = EVP_PKEY_new();

  if (evp == NULL)
    exit(EXIT_FAILURE);

  eck = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);

  if (eck == NULL)
    exit(EXIT_FAILURE);

  asrt(EC_KEY_generate_key(eck), 1, "GENERATE ECK");

  bn = EC_KEY_get0_private_key(eck);

  asrt(BN_bn2bin(bn, pvt), 32, "EXTRACT PVT");

  if (EVP_PKEY_set1_EC_KEY(evp, eck) == 0)
    exit(EXIT_FAILURE);

  cert = X509_new();

  if (cert == NULL)
    exit(EXIT_FAILURE);

  if (X509_set_pubkey(cert, evp) == 0)
    exit(EXIT_FAILURE);

  tm = ASN1_TIME_new();
  if (tm == NULL)
    exit(EXIT_FAILURE);

  ASN1_TIME_set_string(tm, "000001010000Z");
  X509_set_notBefore(cert, tm);
  X509_set_notAfter(cert, tm);

  cert->sig_alg->algorithm = OBJ_nid2obj(8);
  cert->cert_info->signature->algorithm = OBJ_nid2obj(8);

  ASN1_BIT_STRING_set_bit(cert->signature, 8, 1);
  ASN1_BIT_STRING_set(cert->signature, "\x00", 1);

  p = value_c;
  if ((cert_len = (CK_ULONG) i2d_X509(cert, &p)) == 0 || cert_len > sizeof(value_c))
    exit(EXIT_FAILURE);

  publicKeyTemplate[2].ulValueLen = cert_len;

  asrt(funcs->C_Initialize(NULL), CKR_OK, "INITIALIZE");
  asrt(funcs->C_OpenSession(0, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL, NULL, &session), CKR_OK, "OpenSession1");
  asrt(funcs->C_Login(session, CKU_SO, "010203040506070801020304050607080102030405060708", 48), CKR_OK, "Login SO");

  for (i = 0; i < 24; i++) {
    id = i;
    asrt(funcs->C_CreateObject(session, publicKeyTemplate, 3, obj + i), CKR_OK, "IMPORT CERT");
    asrt(funcs->C_CreateObject(session, privateKeyTemplate, 5, obj + i), CKR_OK, "IMPORT KEY");
  }

  asrt(funcs->C_Logout(session), CKR_OK, "Logout SO");

  for (i = 0; i < 24; i++) {
    for (j = 0; j < 10; j++) {

      if(RAND_pseudo_bytes(some_data, sizeof(some_data)) == -1)
        exit(EXIT_FAILURE);

      asrt(funcs->C_Login(session, CKU_USER, "123456", 6), CKR_OK, "Login USER");
      asrt(funcs->C_SignInit(session, &mech, obj[i]), CKR_OK, "SignInit");

      recv_len = sizeof(sig);
      asrt(funcs->C_Sign(session, some_data, sizeof(some_data), sig, &recv_len), CKR_OK, "Sign");

      r_len = 32;
      s_len = 32;

      der_ptr = der_encoded;
      *der_ptr++ = 0x30;
      *der_ptr++ = 0xff; // placeholder, fix below

      r_ptr = sig;

      *der_ptr++ = 0x02;
      *der_ptr++ = r_len;
      if (*r_ptr >= 0x80) {
        *(der_ptr - 1) = *(der_ptr - 1) + 1;
        *der_ptr++ = 0x00;
      }
      else if (*r_ptr == 0x00 && *(r_ptr + 1) < 0x80) {
        r_len--;
        *(der_ptr - 1) = *(der_ptr - 1) - 1;
        r_ptr++;
      }
      memcpy(der_ptr, r_ptr, r_len);
      der_ptr+= r_len;

      s_ptr = sig + 32;

      *der_ptr++ = 0x02;
      *der_ptr++ = s_len;
      if (*s_ptr >= 0x80) {
        *(der_ptr - 1) = *(der_ptr - 1) + 1;
        *der_ptr++ = 0x00;
      }
      else if (*s_ptr == 0x00 && *(s_ptr + 1) < 0x80) {
        s_len--;
        *(der_ptr - 1) = *(der_ptr - 1) - 1;
        s_ptr++;
      }
      memcpy(der_ptr, s_ptr, s_len);
      der_ptr+= s_len;

      der_encoded[1] = der_ptr - der_encoded - 2;

      dump_hex(der_encoded, der_encoded[1] + 2, stderr, 1);

      asrt(ECDSA_verify(0, some_data, sizeof(some_data), der_encoded, der_encoded[1] + 2, eck), 1, "ECDSA VERIFICATION");

      }
  }

  asrt(funcs->C_Logout(session), CKR_OK, "Logout USER");

  asrt(funcs->C_CloseSession(session), CKR_OK, "CloseSession");
  asrt(funcs->C_Finalize(NULL), CKR_OK, "FINALIZE");

}