We were using SWIG to make a C cryptographic utility library available to Perl. We are able to generate keys, create digests, but the signing code causes a segmentation fault, which we believe may be in the OpenSSL code itself but it's difficult to be sure.
This problem only comes up when running the code with SWIG, the native C code works.
In Perl, we call this:
$signature = key_utils::mysignMessageWithPem($pem, $message);
Which calls this code in the .i file:
%newobject mysignMessageWithPem;
%inline %{
char *mysignMessageWithPem(char *pem, char *message) {
char *ret = malloc(145);
char *err = malloc(5);
int errorCode;
memcpy(err, "ERROR", 5);
errorCode = signMessageWithPem(pem, message, &ret);
char *signature = ret;
if (errorCode == NOERROR) {
return signature;
} else {
return err;
}
}
%}
Which calls this C code:
int signMessageWithPem(char *message, char *pem, char **signature) {
unsigned int meslen = strlen(message);
unsigned char *messagebytes = calloc(meslen, sizeof(unsigned char));
ECDSA_SIG *sig = NULL;
memcpy(messagebytes, message, meslen);
EC_KEY *key = NULL;
BIO *in = NULL;
unsigned char *buffer = NULL;
char *sha256ofMsg = calloc(SHA256_HEX_STRING, sizeof(char));
unsigned char *outBytesOfsha256ofMsg = calloc(SHA256_STRING, sizeof(unsigned char));
digestOfBytes(messagebytes, &sha256ofMsg, "sha256", meslen);
sha256ofMsg[64] = '\0';
createDataWithHexString(sha256ofMsg, &outBytesOfsha256ofMsg);
in = BIO_new(BIO_s_mem());
BIO_puts(in, pem);
PEM_read_bio_ECPrivateKey(in, &key, NULL, NULL);
sig = ECDSA_do_sign((const unsigned char*)outBytesOfsha256ofMsg, SHA256_DIGEST_LENGTH, key);
int verify = ECDSA_do_verify((const unsigned char*)outBytesOfsha256ofMsg, SHA256_DIGEST_LENGTH, sig, key);
if(verify != 1) {
return ERROR;
}
int buflen = ECDSA_size(key);
buffer = OPENSSL_malloc(buflen);
int derSigLen = i2d_ECDSA_SIG(sig, &buffer);
char *hexData = calloc(derSigLen, sizeof(char));
memcpy(hexData, buffer-derSigLen, derSigLen);
char *hexString = calloc(derSigLen*2+1, sizeof(char));
hexString[derSigLen * 2] = '\0';
toHexString(hexData, derSigLen, hexString);
memcpy(*signature, hexString, derSigLen*2);
signature[derSigLen * 2] = '\0';
EC_KEY_free(key);
BIO_free_all(in);
free(sha256ofMsg);
free(outBytesOfsha256ofMsg);
free(hexData);
free(hexString);
return NOERROR;
}
And returns Segmentation Fault
. The most informative error we have gotten is perl crashed with SIGSEGV in EC_KEY_get_key_method_data()
The full code is here: https://github.com/aleitner/bitpay-perl/tree/stack-overflow-question
Is this a bug with SSL, or are we doing this wrong?
The answer to this question is: we were calling the arguments in the wrong order.
Seriously. The line:
$signature = key_utils::mysignMessageWithPem($pem, $message);
needed to be:
$signature = key_utils::mysignMessageWithPem($message, $pem);
We were in fact doing something wrong. I was tempted to remove the question, but maybe the answer can serve as a cautionary tale or something.