x509_sign routine fails with ASN1 encoding routine error - ssl

I am writing a simple sSL Server code in C using OpenSSL library.
I use an RSA Private Key PEM file along with it's certificate PEM file as input parameters. Here is how I do this:
EVP_PKEY *pkey= NULL;
pkey = EVP_PKEY_new();
if(EVP_PKEY_set1_RSA(pkey, pkey_RSA) == 0){
printf("RSA_set1_key failed, error 0x%lx\n", ERR_get_error());
const char* error_string = ERR_error_string(ERR_get_error(), NULL);
printf("RSA_set1_key returns %s\n", error_string);
}
printf("An RSA key Object created with modulus and exponent params\n");
EVP_PKEY_assign_RSA(pkey, pkey_RSA);
X509 *x509 = X509_new();
X509_set_version(x509, 2);
ASN1_INTEGER_set(X509_get_serialNumber(x509), 0);
X509_gmtime_adj(X509_get_notBefore(x509), 0);
X509_gmtime_adj(X509_get_notAfter(x509), (long)60*60*24*365);
X509_set_pubkey(x509, pkey);
X509_NAME *name = X509_get_subject_name(x509);
X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC,
(unsigned char *)"IN", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC,
(unsigned char *)"Company", -1, -1, 0);
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
(unsigned char *)"localhost", -1, -1, 0);
X509_set_issuer_name(x509, name);
if(X509_sign(x509, pkey, EVP_sha256()) == 0){
printf("X509_sign failed, error 0x%lx\n", ERR_get_error());
const char* error_string = ERR_error_string(ERR_get_error(), NULL);
printf("X509_sign returns %s\n", error_string);
}
SSL_CTX_use_certificate(ctx, x509);
SSL_CTX_use_PrivateKey(ctx, pkey);
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
This code seems to produce error at X509_sign as follows:
X509_sign failed, error 0x6089095
X509_sign returns error:0D0DC006:asn1 encoding routines:ASN1_item_sign_ctx:EVP lib
I am unable to comprehend the error and proceed. Please advise.
Thanks!

Related

Segmentation fault in libavformat tls_openssl.c:tls_open->SSL_ctrl while using static link 'libdecode.a', however, using 'libdecode.so' works well

source code link: https://gitee.com/yanxiuzi/video-engine
(If you are interested in this issue, please answer me so that you can grant you access to the code.)
current target 'tests' use static link library of target 'decode', I build it on Debian11 by gcc-10.2.1 (it could also easyly build on ubuntu, because of the code used apt install cmd in CMakelists.txt), then run tests, I got a segmentation fault at
SSL_ctrl.
The steps are as follows:(you should clone this repository first)
cmake -B build build
cmake --build build --target all -j
cd build/bin
./tests config/config.json
But if I modify https://gitee.com/yanxiuzi/video-engine/blob/master/CMakeLists.txt line 163 and line 112, change to the linked target 'decode_shared' instead of 'decode', evrything goes well.
After debugging many times, I have not been able to find the reason why libdecode.a crashed but libdecode.so works well.
the CMakelists.txt of target decode and decode_shared see here:
https://gitee.com/yanxiuzi/video-engine/blob/873ca16d25c416c28b9b54eab6d2ed36a689c412/common/decode/CMakeLists.txt
note: if you debug tests use gdb, please exec cmd set follow-fork-mode child before start running, or you may can not catch the place error occured.
I'd love to know the cause of the problem, although in the end I avoided this by changing ffmpeg build flags, which using --enable-gnutls instead of --enable-openssl.
This is the code where the problem occurred. 'SSL_set_tlsext_host_name' is a macro definitions of 'SSL_ctrl'.
static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
{
TLSContext *p = h->priv_data;
TLSShared *c = &p->tls_shared;
BIO *bio;
int ret;
if ((ret = ff_openssl_init()) < 0)
return ret;
if ((ret = ff_tls_open_underlying(c, h, uri, options)) < 0)
goto fail;
// We want to support all versions of TLS >= 1.0, but not the deprecated
// and insecure SSLv2 and SSLv3. Despite the name, SSLv23_*_method()
// enables support for all versions of SSL and TLS, and we then disable
// support for the old protocols immediately after creating the context.
p->ctx = SSL_CTX_new(c->listen ? SSLv23_server_method() : SSLv23_client_method());
if (!p->ctx)
{
av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL));
ret = AVERROR(EIO);
goto fail;
}
SSL_CTX_set_options(p->ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
if (c->ca_file)
{
if (!SSL_CTX_load_verify_locations(p->ctx, c->ca_file, NULL))
av_log(h, AV_LOG_ERROR, "SSL_CTX_load_verify_locations %s\n", ERR_error_string(ERR_get_error(), NULL));
}
if (c->cert_file && !SSL_CTX_use_certificate_chain_file(p->ctx, c->cert_file))
{
av_log(h, AV_LOG_ERROR, "Unable to load cert file %s: %s\n", c->cert_file,
ERR_error_string(ERR_get_error(), NULL));
ret = AVERROR(EIO);
goto fail;
}
if (c->key_file && !SSL_CTX_use_PrivateKey_file(p->ctx, c->key_file, SSL_FILETYPE_PEM))
{
av_log(h, AV_LOG_ERROR, "Unable to load key file %s: %s\n", c->key_file,
ERR_error_string(ERR_get_error(), NULL));
ret = AVERROR(EIO);
goto fail;
}
// Note, this doesn't check that the peer certificate actually matches
// the requested hostname.
if (c->verify)
SSL_CTX_set_verify(p->ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
p->ssl = SSL_new(p->ctx);
if (!p->ssl)
{
av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL));
ret = AVERROR(EIO);
goto fail;
}
#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
p->url_bio_method = BIO_meth_new(BIO_TYPE_SOURCE_SINK, "urlprotocol bio");
BIO_meth_set_write(p->url_bio_method, url_bio_bwrite);
BIO_meth_set_read(p->url_bio_method, url_bio_bread);
BIO_meth_set_puts(p->url_bio_method, url_bio_bputs);
BIO_meth_set_ctrl(p->url_bio_method, url_bio_ctrl);
BIO_meth_set_create(p->url_bio_method, url_bio_create);
BIO_meth_set_destroy(p->url_bio_method, url_bio_destroy);
bio = BIO_new(p->url_bio_method);
BIO_set_data(bio, p);
#else
bio = BIO_new(&url_bio_method);
bio->ptr = p;
#endif
SSL_set_bio(p->ssl, bio, bio);
if (!c->listen && !c->numerichost)
SSL_set_tlsext_host_name(p->ssl, c->host); /// <<<=== backtrace shown segmentation fault here
ret = c->listen ? SSL_accept(p->ssl) : SSL_connect(p->ssl);
if (ret == 0)
{
av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session\n");
ret = AVERROR(EIO);
goto fail;
}
else if (ret < 0)
{
ret = print_tls_error(h, ret);
goto fail;
}
return 0;
fail:
tls_close(h);
return ret;
}

openssl is acting open to any size key

how does openssl works with key as it is taking any size of key (1 byte to any size). What is the procedure to go to actual key here ..
openssl enc -d -des-ecb -in cipher.txt -out text.out -K '530343412312345445123345677812345678812324'
how does openssl works with key ... What is the procedure...
It depends on the program, but procedures are usually consistent across the library. In you example, you are using the openssl dec, so you are using the dec sub-program. The source code is available in <openssl dir>/apps/enc.c (enc and dec are part of enc.c).
Here's the relevant parts:
unsigned char key[EVP_MAX_KEY_LENGTH],iv[EVP_MAX_IV_LENGTH];
unsigned char salt[PKCS5_SALT_LEN];
...
char *hkey=NULL,*hiv=NULL,*hsalt = NULL;
The argument to -K is stored in hkey:
else if (strcmp(*argv,"-K") == 0)
{
if (--argc < 1) goto bad;
hkey= *(++argv);
}
Then, around line 580:
if ((hkey != NULL) && !set_hex(hkey,key,sizeof key))
{
/* Handle failure */
}
set_hex is shown below and hex decodes the argument passed in through -K. It back fills the unused length with 0's via the memset. The unused length is EVP_MAX_KEY_LENGTH minus the length -K argument (after hex decoding).
Finally, around line 610:
if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc))
{
/* Handle failure */
}
Note: -k (small k) takes a different code path and uses EVP_BytesToKey to derive the key.
int set_hex(char *in, unsigned char *out, int size)
{
int i,n;
unsigned char j;
n=strlen(in);
if (n > (size*2))
{
BIO_printf(bio_err,"hex string is too long\n");
return(0);
}
memset(out,0,size);
for (i=0; i<n; i++)
{
j=(unsigned char)*in;
*(in++)='\0';
if (j == 0) break;
if ((j >= '0') && (j <= '9'))
j-='0';
else if ((j >= 'A') && (j <= 'F'))
j=j-'A'+10;
else if ((j >= 'a') && (j <= 'f'))
j=j-'a'+10;
else
{
BIO_printf(bio_err,"non-hex digit\n");
return(0);
}
if (i&1)
out[i/2]|=j;
else
out[i/2]=(j<<4);
}
return(1);
}
My observation to the case gave following conclusion:
It takes hex value
If the size is less then 8 bytes it pads 0
It takes first 8 bytes as key

How to register the personal certificate on windows?

I want to register a personal certificate on windows, so the web server can verify the client's identity. Here is my code (It's hard for me to find the example,so I don't know whether is right or not):
char* pfile = "d:/client.crt";
FILE* fp = fopen(pfile, "r");
char ch;
char buf[10000] = {0};
int i = 0;
while ((ch = fgetc(fp)) != EOF) {
memcpy(buf+i, &ch, 1);
i++;
}
BYTE pBinByte[8192] = {0};
unsigned long binBytes = 8192;
//decode base64
CryptStringToBinaryA( buf, strlen(buf) ,CRYPT_STRING_BASE64HEADER , pBinByte , &binBytes ,NULL,NULL);
HCERTSTORE hMyCertStore = CertOpenSystemStore(NULL, _T("MY"));
int len = binBytes;
PCCERT_CONTEXT pCertContext = CertCreateCertificateContext(
MY_ENCODING_TYPE,
pBinByte,
len);
BOOL addOK = CertAddCertificateContextToStore(
hMyCertStore,
pCertContext,
CERT_STORE_ADD_REPLACE_EXISTING,
NULL);
CertFreeCertificateContext(pCertContext);
CertCloseStore(hMyCertStore, 0);
After I run the code in the xp, it run success. And I can find the certificate in the certmgr.msc.
But I can't see it in the IE browser's setting.
How can I fix that problem? Please tell me. Thanks.
.crt file does not contain private key and to make that work you may wanna install a .pfx file that has both public and private keys. And to install this you can simply double click the file then click install certificate then just complete the import wizard and it will automatically store the certificate under your "Personal" folder of your keystore.

Getting ARP table on iPhone/iPad

I am trying to get the ARP entries on my iPad like here.
When compiling the code to run on my iPad (so not the simulator) I am getting missing header error messages. You can resolve them by copying the header files into you project locally as mentioned in this post.
The problem lies in the line
sdl = (struct sockaddr_dl *)(sin + 1);
in this piece of code:
-(NSString*) ip2mac: (char*) ip
{
int expire_time, flags, export_only, doing_proxy, found_entry;
NSString *mAddr = nil;
u_long addr = inet_addr(ip);
int mib[6];
size_t needed;
char *host, *lim, *buf, *next;
struct rt_msghdr *rtm;
struct sockaddr_inarp *sin;
struct sockaddr_dl *sdl;
extern int h_errno;
struct hostent *hp;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = AF_INET;
mib[4] = NET_RT_FLAGS;
mib[5] = RTF_LLINFO;
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
err(1, "route-sysctl-estimate");
if ((buf = malloc(needed)) == NULL)
err(1, "malloc");
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
err(1, "actual retrieval of routing table");
lim = buf + needed;
for (next = buf; next < lim; next += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *)next;
sin = (struct sockaddr_inarp *)(rtm + 1);
sdl = (struct sockaddr_dl *)(sin + 1);
if (addr) {
if (addr != sin->sin_addr.s_addr)
continue;
found_entry = 1;
}
if (nflag == 0)
hp = gethostbyaddr((caddr_t)&(sin->sin_addr),
sizeof sin->sin_addr, AF_INET);
else
hp = 0;
if (hp)
host = hp->h_name;
else {
host = "?";
if (h_errno == TRY_AGAIN)
nflag = 1;
}
if (sdl->sdl_alen) {
u_char *cp = LLADDR(sdl);
mAddr = [NSString stringWithFormat:#"%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]];
// ether_print((u_char *)LLADDR(sdl));
}
else
mAddr = nil;
}
if (found_entry == 0) {
return nil;
} else {
return mAddr;
}
}
It gives the following error message:
Arithmetic on pointer to incomplete type 'struct sockaddr_inarp*'
When you compile the code for the iPad simulator everything runs fine.
Does anyone have an idea how to solve this?
A similar question (but not solved) is asked here.
After importing <netinet/if_ether.h>, you should edit it and change the line
#include <net/if_arp.h>
to
#include "if_arp.h"
and then import <net/if_arp.h> in your project as well. This should fix that error.
Anyway the headers you need to import to compile the code you posted are:
#include "if_ether.h"
#include "route.h"
#include "if_arp.h"
#include "if_dl.h"
Hope this helps =)
EDIT:
You need to "Add files to project", not simply importing it with #import or #include.
You can find above files from following links:
Files under "netinet"
Files under "net"
#include <net/ethernet.h>
instead of messing with the original headers. More info here: Implicit declaration of function 'ether_ntoa' is invalid in C99

OpenSSL gost engine issue

I'm trying to implement ECDH key exchange GOST 34.10-2001 using OpenSSL 1.0.0d.
I'm loading gost engine like this:
ENGINE * e = ENGINE_by_id("gost");
if(!e)
{
e = ENGINE_by_id("dynamic");
if (!e)
{
ENGINE_load_dynamic();
e = ENGINE_by_id("dynamic");
}
if (e && (!ENGINE_ctrl_cmd_string(e, "SO_PATH", "gost", 0) || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)))
return 1;
}
if(!ENGINE_init(e))
return 1;
ENGINE_set_default(e, ENGINE_METHOD_ALL);
OpenSSL_add_all_algorithms();
At this point GOST engine is loaded and works fine (I think so). I've done some testings with hashing and encryption algorithms.
But when I'm trying to implement ECDH (shared key generation by importing other side public key), I'm getting improper result (shared key differs with other side).
I've checked a, b, p, q, x, y parameters, checked code flow, but can't figure out what's wrong.
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94
a6
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C611070995AD10045841B09B761B893
1
8D91E471E0989CDA27DF505A453F2B7635294F2DDF23E3B122ACC99C9E9F1E14
There's one thing: VKO 34.10-2001 algorithm is implemented in openssl\engines\ccgost\gost2001_keyx.c (function VKO_compute_key), BUT when I'm calling a generic function ECDH_compute_key it doesn't lead to VKO_compute_key (checked this by setting int3 at the beginning of VKO_compute_key).
Did I misunderstood something? Or can someone show an example of generating shared key using gost engine from openssl?
I know it's an old question, but it may still be topical for some.
The following code generates a shared secret just fine when using the GOST engine.
int get_shared_key(
EVP_PKEY *priv,
EVP_PKEY *peer,
unsigned char *ukm,
int ukm_size,
unsigned char *secret,
size_t *secret_len)
{
int result = 0;
EVP_PKEY_CTX *ctx = NULL;
int key_size = 0;
if((ctx = EVP_PKEY_CTX_new(priv, NULL)) == NULL)
goto err;
if(EVP_PKEY_derive_init(ctx) != 1)
goto err;
if(EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_DERIVE, EVP_PKEY_CTRL_SET_IV, ukm_size, ukm) != 1)
goto err;
if(EVP_PKEY_derive_set_peer(ctx, peer) != 1)
goto err;
key_size=EVP_PKEY_derive(ctx, NULL, secret_len);
if(key_size != GOST_R_34_12_2015_KEY_SIZE)
goto err;
if(EVP_PKEY_derive(ctx, secret, secret_len) != 1)
goto err;
result = 1;
goto end;
err:
ERR_print_errors_fp(stderr);
end:
if(ctx)
EVP_PKEY_CTX_free(ctx);
return result;
}