OpenSSL 1.0.0 RSA parameters in C - c

I realized that I cannot use the function RSA_get0_key in OpenSSL 1.0.0 to extract the values of n, e, d by reading the private key from a file and passing it as parameter to the aforementioned function.
It is not a programming issue, I mean, I know how to use the functions, but I don't know if there is an alternative to do this.
Indeed, the warning that stops me during the compiling operation is the following:
warning: implicit declaration of function ‘RSA_get0_key’; did you mean ‘RSA_check_key’? [-Wimplicit-function-declaration]
Do you know how to do that? I check the manual here (https://www.openssl.org/docs/man1.0.2/man3/) but it seems that there isn't a properly function to make this. Further, I need to be compliant to OpenSSL 1.0.0.
Code
#include <stdio.h>
#include <stdlib.h>
#include <openssl/rsa.h>
#include <openssl/obj_mac.h>
#include <openssl/rand.h>
#include <openssl/bn.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/pem.h>
int main()
{
OpenSSL_add_all_algorithms();
ERR_load_crypto_strings();
RSA *privkey = RSA_new();
FILE *privkeyfile = fopen("private.key", "rb");
PEM_read_RSAPrivateKey(privkeyfile, &privkey, NULL, NULL);
fclose(privkeyfile);
BIGNUM *n, *e, *d = NULL;
RSA_get0_key(privkey,&n,&e,&d);
return 0;
}

The RSA_get0_key function was added in OpenSSL 1.1.0 as an abstraction to retrieve the n, e, and d values for an RSA key. For earlier versions you need to access the fields directly.
n = privkey->n;
e = privkey->e;
d = privkey->d;
If you want your code to be able to handle 1.0.x and 1.1.x, you can check the value of OPENSSL_VERSION_NUMBER:
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
RSA_get0_key(privkey, &n, &e, &d);
#else
n = privkey->n;
e = privkey->e;
d = privkey->d;
#endif

Related

Build RSA-Signature of a file with libgmp

I want to implement RSA-Signature where I can calculate the signature of a file and verify a signature of a file. Therefore I use the libary gmp.
But when I want to print the data of the file, it always prints 0 even though the file is not empty. Here is my code:
//compiled with gcc rsa-sig.c -O3 -Wall -l gmp -o rsa-sig
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#include <math.h>
#include <gmp.h> /* GNU Multi Precision library */
int main(int argc, char *argv[])
{
int r;
mpz_t modulus;
mpz_init(modulus);
r=mpz_set_str(modulus, "FFFF",16); //just an example modulus
mpz_t data;
mpz_init(data);
FILE * stream;
stream = fopen("file.bin", "rb");
r= mpz_inp_str(data, stream,16);
mpz_mod(data,data,modulus);
gmp_printf("%Zd\n",data);
}
I can't figure out why the output of that is 0. Maybe one of you guys have an idea.
Thanks!!

Why does this MEXed C/magma code seg-fault while the stand alone C code works?

The following MEXed C code simply makes calls to magma to invert a matrix. The stand alone C code (which is also posted) works, but the mex code crashes.
I've triple checked the documentation, verified that other magma functions work as expected, and posted on the Magma forum and was told my code is fine (this post is a cross post from Magma forum). This means that the problem is with mex. I would like to know what is causing the mex code to seg-fault and how to get it to run as expected.
Mexed code:
#include <mex.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stddef.h>
#include <magma_v2.h>
#include <cuda_runtime.h>
void mat2magma(magmaDoubleComplex* p, double* pr, double* pi,int numElements)
{
int j=0;
for(j=0;j<numElements;j++){
p[j].x=pr[j];
p[j].y=pi[j];
}
}
void magma2mat(magmaDoubleComplex* p, double* pr, double* pi,int numElements)
{
int j=0;
for(j=0;j<numElements;j++){
pr[j]= p[j].x;
pi[j]= p[j].y;
}
}
/*gateway function*/
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]) {
/*initialize magma*/
magma_init();
magma_queue_t queue = NULL;
magma_device_t dev;
magma_getdevice(&dev);
magma_queue_create(dev,&queue );
magma_int_t m,ldwork,info;
magma_int_t *piv;
magmaDoubleComplex *a,*da,*dwork;
/* Matlab -> Host */
m=mxGetM(prhs[0]);
piv=(magma_int_t*) malloc(m*sizeof(magma_int_t));
magma_zmalloc_cpu(&a,m*m);
mat2magma(a,mxGetPr(prhs[0]),mxGetPi(prhs[0]),m*m);
ldwork = m*magma_get_zgetri_nb(m);
/* Host -> GPU */
magma_zmalloc(&dwork,ldwork);
magma_zmalloc(&da,m*m);
magma_zsetmatrix(m,m,a,m,da,m,queue);
/*LU and Inverse */
magma_zgetrf_gpu(m,m,da,m,piv,&info);
magma_zgetri_gpu(m,da,m,piv,dwork,ldwork,&info);
/*GPU -> Host */
magma_zgetmatrix(m,m,da,m,a,m,queue);
/*Host -> Matlab*/
plhs[0] = mxCreateDoubleMatrix(m,m,mxCOMPLEX);
magma2mat(a,mxGetPr(plhs[0]),mxGetPi(plhs[0]),m*m);
free(a);
free(piv);
magma_free(dwork);
magma_free(da);
magma_queue_destroy(queue);
magma_finalize();
}
I compliled it with mex CC=gcc LDFLAGS="-lmagma -lcudart -lcublas" magmaZinv.c then from matlab, I ran:
a=magic(3)+magic(3)*1i;
magmaZinv(a)
Standalone C code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stddef.h>
#include <magma_v2.h>
#include <cuda_runtime.h>
#include <sys/time.h>
#include <time.h>
/*gateway function*/
int main() {
/*initialize magma*/
magma_init();
magma_queue_t queue = NULL;
magma_device_t dev;
magma_getdevice(&dev);
magma_queue_create(dev,&queue );
int m,ldwork,info;
int *piv;
magmaDoubleComplex *a,*da,*dwork;
/* allocate and initialize a = magic(3)+magic(3)*1i; */
m=3;
piv=(int*) malloc(m*sizeof(int));
ldwork = m*magma_get_zgetri_nb(m);
magma_zmalloc_cpu(&a,m*m);
a[0].x=8;a[0].y=8;
a[1].x=3;a[1].y=3;
a[2].x=4;a[2].y=4;
a[3].x=1;a[3].y=1;
a[4].x=5;a[4].y=5;
a[5].x=9;a[5].y=9;
a[6].x=6;a[6].y=6;
a[7].x=7;a[7].y=7;
a[8].x=2;a[8].y=2;
/* Host -> GPU */
magma_zmalloc(&dwork,ldwork);
magma_zmalloc(&da,m*m);
magma_zsetmatrix(m,m,a,m,da,m,queue);
/*LU and Inverse */
magma_zgetrf_gpu(m,m,da,m,piv,&info);
magma_zgetri_gpu(m,da,m,piv,dwork,ldwork,&info);
/*GPU -> Host */
magma_zgetmatrix(m,m,da,m,a,m,queue);
/* display inv(a) */
for (int i=0;i<(m*m);i++){
printf("%f +%fi\n",a[i].x,a[i].y);
}
/* free memory */
free(a);
free(piv);
magma_free(dwork);
magma_free(da);
magma_queue_destroy(queue);
magma_finalize();
return 0;
}
I compiled with: gcc -lmagma -lcudart Ccode.c -o Ccode.o
My sys admin has figured out why the standalone C code works while the mexed C code does not. I'll post the reason here incase it is helpful to anyone facing the same issues when using Magma from within Matlab.
The version of Matlab I was using was 2014a. The supported compiler for this version is 4.7.x. I was using a higher version of gcc to compile the code. I've never had a problem with using different versions of GCC with matlab, despite the warning it gives, but for the above code it does matter.
Compile with the MKL_ilp64 flag when using Magma with Matlab to ensure that magma_int_t is int64.
With these two suggestions, Magma can be mexed into matlab with no problems.

Why does the agwrite function in the cgraph library unexpectedly fail on any config/platform but Win64 release?

I've been trying to get cgraph (https://graphviz.gitlab.io/_pages/pdf/cgraph.pdf) working so I read and write some graph files. I tried writing some very basic code:
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include <memory.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Windows.h>
#include <mysql.h>
#include <graphviz/cgraph.h>
int main() {
FILE *fp = NULL;
fp = fopen("test.dot", "w+");
if (fp == NULL) {
return -1;
}
Agraph_t *g;
g = agopen("test", Agdirected, NULL);
Agnode_t *signal1;
signal1 = agnode(g, "Signal1_ON", TRUE);
Agnode_t *signal2;
signal2 = agnode(g, "Signal1_OFF", TRUE);
Agedge_t *link = agedge(g, signal1, signal2, "link1", TRUE);
agattr(g, AGEDGE, "label", "transitionlink");
agwrite(g, fp);
fclose(fp);
system("pause");
return 0;
}
What should be happening is that the file should be written to test.dot. This code works perfectly fine on Win64 release, but fails on Win64 debug, Win32 debug, and Win32 release. I have double checked the .lib files and .dll files settings in visual studio and in the file directories, making sure to copy the release and debug versions of each platform correctly. However, the agwrite keeps causing a "Microsoft Visual Studio C Runtime Library has detected a fatal error" crash on Win64 debug, Win32 debug, and Win32 release. The weird thing is if I change
agwrite(g, fp); to agwrite(g, stdout);, the code works on all platforms/configurations. I am so confused why this is happening. Here is the source file which contains the code for agwrite if that helps: https://github.com/ellson/MOTHBALLED-graphviz/blob/master/lib/cgraph/write.c
I cannot debug the issue because the source has been compiled into .dlls, and .libs for each platform/configuration.
I appreciate any suggestions/feedback,
Thank you
Edit:
For anyone godly enough to try and get this working on their own system, here are all my binaries, libs, and include files: https://www.dropbox.com/sh/o9tjz7txu4m0k5q/AAAnp8Wu99q9IsFN7kvqZP7Ta?dl=0
Edit 2:
The compiler I am using is MSVC 14 on Windows 10.
I found out that using cgraph directly results in an error when trying to use agwrite(). The solution is to use the GVC abstraction layer which comes with the Graphviz C API to do file I/O. Here is the code that worked:
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include <memory.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Windows.h>
#include <mysql.h>
#include <graphviz/gvc.h>
int main() {
GVC_t *gvc;
gvc = gvContext();
Agraph_t *g;
g = agopen("test", Agdirected, NULL);
Agnode_t *signal1;
signal1 = agnode(g, "Signal1_ON", TRUE);
Agnode_t *signal2;
signal2 = agnode(g, "Signal1_OFF", TRUE);
Agedge_t *link = agedge(g, signal1, signal2, "link1", TRUE);
agattr(g, AGEDGE, "label", "transitionlink");
gvLayout(gvc, g, "dot");
gvRenderFilename(gvc, g, "dot", "test.dot");
gvFreeLayout(gvc, g);
agclose(g);
gvFreeContext(gvc);
system("pause");
return 0;
}
Edit:
Here is the documentation for GVC: https://graphviz.gitlab.io/_pages/pdf/gvc.3.pdf
The reason of crashing is described on official Graphviz site:
This usually happens when the Graphviz library is built using one version of the stdio library, and the user’s program is compiled using another. If the FILE structure of stdio is different, the call to agread() will cause a crash. This is mainly a problem on Windows where we just provide a binary release built with one version of Visual Studio and stdio changes depending on the version of Visual Studio. It can also occur if the user tries to use cygwin or something similar which may also use an incompatible stdio.
https://graphviz.org/faq/#FaqAgreadCrash

Setting Immutable Flag using ioctl() in C

I have attempted to make a script that creates a file and then sets it as immutable similar to the chattr +i command for linux. The script compiles (with gcc), runs and the file is created. However the file itself is not immutable and can be removed with a simple rm -f. I have attempted to stacktrace where chattr is called and I found a function called ioctl. I then used what little information I could gather and came up with what I have below. I narrowed it down from ext2_fs.h but it just doesn't seem to work. I've clearly overlooked something.
Updates to previous entry: Compiles but returns -1 on ioctl() function. Bad address shown with perror().
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
int main()
{
FILE *fp;
char shovel[16] = "I have a shovel!";
fp = fopen("/shovel.txt", "w+");
fwrite(shovel, sizeof(shovel[0]), sizeof(shovel)/sizeof(shovel[0]), fp);
ioctl(fileno(fp), FS_IOC_SETFLAGS, 0x00000010);
fclose(fp);
}
Any help appreciated.
You are using the right ioctl command, but you're passing it the wrong arguments.
The manpage for ioctl_list(2) shows that FS_IOC_SETFLAGS expects to receive a pointer to int (an int *), yet you're passing it an integer literal (hence the Bad Address error).
The fact that you don't to any error checking whatsoever is also not helping.
The correct flag to pass to FS_IOC_SETFLAGS is a pointer holding the value EXT2_IMMUTABLE_FL, which is defined in ext2fs/ext2_fs.h (some older / different Linux distributions seem to have it under linux/ext2_fs.h), so you'll need to #include <ext2fs/etx2_fs.h>. Make sure to install e2fslibs-dev (and probably you'll need linux-headers too).
This code is working:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <ext2fs/ext2_fs.h>
int main()
{
FILE *fp;
char shovel[16] = "I have a shovel!";
if ((fp = fopen("shovel.txt", "w+")) == NULL) {
perror("fopen(3) error");
exit(EXIT_FAILURE);
}
fwrite(shovel, sizeof(shovel[0]), sizeof(shovel)/sizeof(shovel[0]), fp);
int val = EXT2_IMMUTABLE_FL;
if (ioctl(fileno(fp), FS_IOC_SETFLAGS, &val) < 0)
perror("ioctl(2) error");
fclose(fp);
return 0;
}
Remember to run this as root.
UPDATE:
As Giuseppe Guerrini suggests in his answer, you might want to use FS_IMMUTABLE_FL instead, and you won't need to include ext2_fs.h:
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
int main()
{
FILE *fp;
char shovel[16] = "I have a shovel!";
if ((fp = fopen("shovel.txt", "w+")) == NULL) {
perror("fopen(3) error");
exit(EXIT_FAILURE);
}
fwrite(shovel, sizeof(shovel[0]), sizeof(shovel)/sizeof(shovel[0]), fp);
int val = FS_IMMUTABLE_FL;
if (ioctl(fileno(fp), FS_IOC_SETFLAGS, &val) < 0)
perror("ioctl(2) error");
fclose(fp);
return 0;
}
The main problem is that the ioctl wants a pointer to the mask, not a direct constant. You have to define a int variable, store the mask (0x10) in it and pass its address as third argument of ioctl.
Also, I'd add some hints:
other programs to change attributes are used to use low-level I/O directly (open, close...). Also, the file is usually opened with O_RDONLY.
Use FS_IMMUTABLE_FL istead the raw constant.
Get the current attribute mask first (FS_IOC_SETFLAGS) and mask it with the new flag, so other settings are not lost by the service.

Ruby C Extensions, loading external libraries

I'm trying to build a Ruby C Extension for Raspberry Pi using some existing C code. The code relies on the bcm2835-1.35 library for some functions. Problem is that when I try to run the a ruby program using on the RPi, I get the following:
ruby: symbol lookup error: /usr/lib/ruby/site_ruby/2.1.0/armv6l-linux-eabihf/dht_test.so: undefined symbol: bcm2835_gpio_fsel
Here's what the code looks like, this is all in one directory (~/Ruby/dht_test)
extconf.rb
# Loads mkmf which is used to make makefiles for Ruby extensions
require 'mkmf'
# Load Libraries
LIBDIR = RbConfig::CONFIG['libdir']
INCLUDEDIR = RbConfig::CONFIG['includedir']
HEADER_DIRS = [
# First search /opt/local for macports
'/opt/local/include',
# Then search /usr/local for people that installed from source
'/usr/local/include',
# Check the ruby install locations
INCLUDEDIR,
# Finally fall back to /usr
'/usr/include',
]
LIB_DIRS = [
# Then search /usr/local for people that installed from source
'/usr/local/lib',
# Check the ruby install locations
LIBDIR,
# Finally fall back to /usr
'/usr/lib',
]
unless find_header('bcm2835.h')
abort 'bcm2835 is missing'
end
dir_config('bcm2835', HEADER_DIRS, LIB_DIRS) # Tried with the line commented out, doesn't make any difference
# Give it a name
extension_name = 'dht_test'
# The destination
dir_config(extension_name)
# Do the work
create_makefile(extension_name)
dhtreader.h
/* for usleep */
//#define _BSD_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <assert.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <bcm2835.h>
#include <unistd.h>
int readDHT(int type, int pin, float *temp_p, float *hum_p);
dhtreader.c
#include "dhtreader.h"
int readDHT(int type, int pin, float *temp_p, float *hum_p)
{
int counter = 0;
int laststate = HIGH;
int i = 0;
int j = 0;
int checksum = 0;
#ifdef DEBUG
int bitidx = 0;
int bits[250];
#endif
int data[100];
// Set GPIO pin to output
bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_write(pin, HIGH);
usleep(500000); // 500 ms
bcm2835_gpio_write(pin, LOW);
usleep(20000);
bcm2835_gpio_fsel(pin, BCM2835_GPIO_FSEL_INPT);
ect....
dht_test.c
// Include the Ruby headers and goodies
#include "ruby.h"
#include "dhtreader.h"
// Defining a space for information and references about the module to be stored internally
VALUE DhtTest = Qnil;
// Prototype for the initialization method - Ruby calls this, not you
void Init_dht_test();
// Prototype for our method 'test1' - methods are prefixed by 'method_' here
VALUE method_test1(VALUE self);
VALUE method_test2(VALUE self);
// The initialization method for this module
void Init_dht_test() {
DhtTest = rb_define_module("DhtTest");
rb_define_method(DhtTest, "test1", method_test1, 0);
rb_define_method(DhtTest, "test2", method_test2, 0);
}
// Our 'test1' method.. it simply returns a value of '10' for now.
VALUE method_test1(VALUE self) {
int x = 10;
return INT2NUM(x);
}
VALUE method_test2(VALUE self){
float temp;
float hum;
readDHT(22, 4, &temp, &hum);
printf("Temperture: %f, Humidity %f", temp, hum);
return temp;
}
Finally
I try to run the following irb, the first function test1 works fine, the second function which requires the bcm2835 fails with the previously stated error
require 'dht_test'
include DhtTest
puts test1
puts test2
I'm new to this stuff and I'm sure I'm making some egregious mistakes, but I'm pretty much stuck and would appreciate any help I can get.
Figured it out, I needed to add the following to my extconf.rb
unless have_library('bcm2835') && append_library($libs, 'bcm2835')
abort "Unable to appended Library bcm2835!"
end
Also this is needed to compile in c99
$CFLAGS << ' -std=c99' // yes you need the space

Resources