key_add is returning same signature values - c

so im trying to add ecryptfs fnek and fekek signatures to the user keyring and im using openssl to generate a random payload for the keys but for some reason the signatures are the same each time i run my program even though RAND_priv_bytes doesn't fail and the value of random_bytes changes each time but the signature stays the same.
here is the code currently.
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#include <keyutils.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
int main(){
key_serial_t fekek_sig;
key_serial_t fnek_sig;
const int BYTE_NUM = 496;
char random_bytes[BYTE_NUM];
const EVP_MD *md = NULL;
const EVP_MD *md2 = NULL;
EVP_MD_CTX *md_ctx = NULL;
EVP_MD_CTX *md2_ctx = NULL;
unsigned char md_res[EVP_MAX_MD_SIZE], md2_res[EVP_MAX_MD_SIZE];
unsigned int md_len, md2_len;
const char KEY_TYPE[] = "user";
const char FEKEK_DESC[] = "EcryptFS FEKEK Signature";
const char FNEK_DESC[] = "EcryptFS FNEK Signature";
md = EVP_get_digestbyname("SHA512");
md2 = EVP_get_digestbyname("BLAKE2B512");
md_ctx = EVP_MD_CTX_new();
md2_ctx = EVP_MD_CTX_new();
EVP_DigestInit_ex(md_ctx, md, NULL);
EVP_DigestInit_ex(md2_ctx, md2, NULL);
int rc;
rc = RAND_priv_bytes(random_bytes, BYTE_NUM);
if (rc == 1)
{
EVP_DigestUpdate(md_ctx, random_bytes, BYTE_NUM);
}
else if (rc == -1 || rc == 0)
{
fprintf(stderr, "%d\n", ERR_get_error());
}
rc = RAND_priv_bytes(random_bytes, BYTE_NUM);
if (rc == 1)
{
EVP_DigestUpdate(md2_ctx, random_bytes, BYTE_NUM);
}
else if (rc == -1 || rc == 0)
{
fprintf(stderr, "%d\n", ERR_get_error());
}
EVP_DigestFinal_ex(md_ctx, md_res, &md_len);
EVP_DigestFinal_ex(md2_ctx, md2_res, &md2_len);
fekek_sig = add_key(KEY_TYPE, FEKEK_DESC, md_res, md_len, KEY_SPEC_USER_KEYRING);
fnek_sig = add_key(KEY_TYPE, FNEK_DESC, md2_res, md2_len, KEY_SPEC_USER_KEYRING);
EVP_MD_CTX_free(md_ctx);
EVP_MD_CTX_free(md2_ctx);
printf("FEKEK=%d\nFNEK=%d\n", fekek_sig, fnek_sig);
return 0;
}
and this is what gets printed
$ gcc main.c -o test -lkeyutils -lssl -lcrypto
$ ./test
FEKEK=570453362
FNEK=791909717
$ ./test
FEKEK=570453362
FNEK=791909717
does anyone know why this is?

Related

Why can’t I get ENODATA from Setxattr?

The following is always meeting the ENOENT condition at the end. I would like to print ENODATA. What do I need to change in setxattr?
#include <sys/xattr.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main() {
int ret;
const char * file = "non_existent_file.txt";
const char * name = "user.test";
const char * value = "value";
ssize_t size = strlen(value);
printf("Setting Xattr\n");
ret = setxattr(file, name, value, size, XATTR_REPLACE);
if (ret == -1) {
printf("Xattr set failed: %s\n", strerror(errno));
perror("");
}
if (errno == ENODATA) {
printf("ENODATA\n");
}
if (errno == ENOENT) {
printf("ENOENT\n");
}
return 0;
}
I get “ENOENT” printed from last condition end statements
I tried adding the XATTR_REPLACE flag.
I’ve removed valid paths for the file path
Edit:
Target OS: Ubuntu/ Linux

How to check password on macOS?

The following C program can check the password of a user on Linux.
But it does not work on macOS because some functions are Linux specific.
Could anybody show me how to revise the program so that it works on macOS?
#include <unistd.h>
#include <pwd.h>
#include <shadow.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
char *username = argv[1];
struct passwd *pwd = getpwnam(username);
if (pwd == NULL) {
fputs("couldn't get password record", stderr);
return 1;
}
struct spwd *spwd = getspnam(username);
if (spwd == NULL) {
if(errno == EACCES) {
fputs("no permission to read shadow password file", stderr);
return 1;
}
fputs("No such username", stderr);
return 1;
}
char *password = getpass("Password: ");
printf("spwd->sp_pwdp: %s\n", spwd->sp_pwdp);
char *encrypted = crypt(password, spwd->sp_pwdp);
for (char *p = password; *p != '\0'; ++p)
*p = '\0';
if (encrypted == NULL) {
perror("crypt");
return 1;
}
if (strcmp(encrypted, spwd->sp_pwdp) != 0) {
fputs("Incorrect password\n", stderr);
return 1;
}
printf("Successfully authenticated: UID=%d\n", pwd->pw_uid);
return 0;
}
$ sudo ./checkpass "$USER"
Password:
spwd->sp_pwdp: $y$j9T$F5Jx5fExrKuPp53xLKQ..1$X3DX6M94c7o.9agCG9G317fhZg9SqC.5i5rd.RhAtQ7
Successfully authenticated: UID=504
Both Linux and macOS use PAM for authentication; Linux uses Linux-PAM, and MacOS and BSDs OpenPAM.
To authenticate via PAM:
/*
This is a variant of the Linux-PAM example at
http://www.linux-pam.org/Linux-PAM-html/adg-example.html
modified to use the 'login' PAM service.
That program was contributed by Shane Watts
[modifications by AGM and kukuk]
Save as ex_login.c, compile using (for Linux-PAM):
gcc -Wall -Wextra -O2 ex_login.c -lpam -lpam_misc -o ex_login
or (for OpenPAM):
gcc -DOPENPAM -Wall -Wextra -O2 ex_login.c -lpam -o ex_login
and run
./ex_login username
to authenticate the specified user.
*/
#include <stdlib.h>
#include <security/pam_appl.h>
#ifdef OPENPAM
#include <security/openpam.h>
#define USE_CONV_FUNC openpam_ttyconv
#else
#include <security/pam_misc.h>
#define USE_CONV_FUNC misc_conv
#endif
#include <stdio.h>
static struct pam_conv conv = {
USE_CONV_FUNC,
NULL
};
int main(int argc, char *argv[])
{
const char *arg0 = (argc > 0 && argv && argv[0] && argv[0][0] != '\0') ? argv[0] : "(this)";
pam_handle_t *pamh = NULL;
int retval;
const char *user;
if (argc != 2) {
fprintf(stderr, "\nUsage: %s USERNAME\n\n", arg0);
exit(EXIT_FAILURE);
}
user = argv[1];
retval = pam_start("login", user, &conv, &pamh);
if (retval == PAM_SUCCESS)
retval = pam_authenticate(pamh, 0); /* is user really user? */
if (retval == PAM_SUCCESS)
retval = pam_acct_mgmt(pamh, 0); /* permitted access? */
/* This is where we have been authorized or not. */
if (retval == PAM_SUCCESS) {
fprintf(stdout, "Authenticated\n");
} else {
fprintf(stdout, "Not Authenticated\n");
}
if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
pamh = NULL;
fprintf(stderr, "%s: failed to release authenticator\n", arg0);
exit(EXIT_FAILURE);
}
return ( retval == PAM_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE );
}

Create file recursive in C Linux

I want to create file test in this path /tmp/a1/a2/a3/a4/test
But all the directories (a1..a4) doesn't exist, How can I create this file in C at Linux OS?
You can use the mkdir function from sys/stat.h to create the directories as you need them. E.g.,
mkdir("/tmp/a1",0766);
However, you should check, via stat, whether or not the directories exist already.
Once you've created the directory structure, your file can be created with
open("/tmp/a1/a2/a3/a4/test",O_WRONLY|O_CREAT);
Obviously, you need to check the return values of all of these function calls.
Below is a complete function in C that achieves what you want.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
int create_file_with_parent_dirs (char pathname[])
{
for (char *p = pathname; (p = strchr(p ,'/')) != NULL; ++p) {
char c = p[1];
p[1] = '\0';
errno = 0;
if (mkdir(pathname, 0700) != 0 && errno != EEXIST) {
perror("mkdir");
return -1;
}
p[1] = c;
}
int fd = creat(pathname, 0600);
if (fd < 0)
perror("creat");
return fd;
}
int main (void)
{
char pathname[] = "/tmp/a1/a2/a3/a4/test";
create_file_with_parent_dirs(pathname);
}
Note that the array pointed to by pathname must be modifiable. Do not call the function with a string literal. Also beware that the file will be truncated to zero length if it already exists.
You can use this code. This program split the path and check whether the path exist or not if not create the path and create the final path as file.
#include <dirent.h>
#include <errno.h>
#include <bits/stdc++.h>
#include <iostream>
#include <sys/stat.h>
#include <sys/types.h>
#include <vector>
#include <fstream>
using namespace std;
int checkDir(char * path)
{
DIR* dir = opendir(path);
if (dir) {
/* Directory exists. */
closedir(dir);
return 0;
} else if (ENOENT == errno) {
/* Directory does not exist. */
return -1;
} else {
/* opendir() failed for some other reason. */
return -2;
}
}
int make_dir(char *path)
{
int ret = checkDir(path);
if( ret == -1)
{
if (mkdir(path, 0777) == -1)
{
cerr << "Error : " << strerror(errno) << endl;
return -1;
}
else
{
cout << "Directory created";
return 0;
}
}
return ret;
}
int main(int args, char **argv)
{
std::string strpath(argv[1]);
std::string delimeter = "/";
std::string substr1 = "";
int cnt = 0;
std::vector<string> strPaths;
std::string strbck = strpath;
for( int i = strpath.find(delimeter); i != std::string::npos; i = strpath.find(delimeter))
{
if(cnt > 0)
{
substr1 = strbck.substr(0, substr1.length() + i + 1);
strPaths.push_back(substr1);
}
strpath = strpath.substr(i +1,strpath.length());
cnt++;
}
strPaths.push_back(strbck);
std::string str;
for_each( strPaths.begin() ,strPaths.end() -1 , [](std::string str) {make_dir((char*)str.c_str());});
ofstream outfile;
std::ofstream file {strPaths[strPaths.size() -1].c_str() };
file << "hello"<< std::endl;
file.close();
return 0;
}

Revoke existing certificate in openssl

I have created openssl certificates so i have .crt and .key file. If I want to add those certificates in existing certificate revocation list then how can we do that ?
I have tried with below code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <openssl/pem.h>
#include <openssl/conf.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/ssl.h>
#include <openssl/evp.h>
#include <openssl/asn1.h>
#define DB_NUMBER 6
#define DB_name 5
#define DB_serial 3
#define DB_rev_date 2
static X509* load_cert(const char* usercert)
{
/* read usercert from file */
X509* x = NULL;
BIO* bio = BIO_new(BIO_s_file());
assert(bio != NULL);
assert(BIO_read_filename(bio, usercert) > 0);
x = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL);
BIO_free(bio);
assert(x != NULL);
return x;
}
int main()
{
int i;
ASN1_UTCTIME* tm = NULL;
char* rev_str = NULL;
BIGNUM* bn = NULL;
char* row[DB_NUMBER];
for (i = 0; i < DB_NUMBER; i++)
row[i] = NULL;
X509* x = load_cert("../client.crt");
row[DB_name] = X509_NAME_oneline(X509_get_subject_name(x), NULL, 0);
bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(x), NULL);
assert(bn != NULL);
if (BN_is_zero(bn))
row[DB_serial] = BUF_strdup("00");
else
row[DB_serial] = BN_bn2hex(bn);
BN_free(bn);
//assert(row[DB_name] != NULL);
//assert(row[DB_serial] != NULL);
printf("Serial Number is: %s\n", row[DB_serial]);
printf("---- Now Updating CRL file with expired client certificates --------\n");
char *crl_file_path = "../root_mod.crl";
FILE *fp_crl_file = NULL;
X509_CRL *x_crl = NULL;
BIGNUM* serial = NULL;
/* Get the CA crl */
fp_crl_file = fopen(crl_file_path, "r");
if (!fp_crl_file)
{
printf("---- Error while opening CRL file --------\n");
exit(1);
}
x_crl = PEM_read_X509_CRL(fp_crl_file, NULL, NULL, NULL);
if (!x_crl)
{
printf("---- Error while reading X509 CRL file --------\n");
exit(1);
}
fclose(fp_crl_file);
X509_REVOKED* r = X509_REVOKED_new();
assert(r != NULL);
assert(BN_hex2bn(&serial, row[DB_serial]) > 0);
ASN1_INTEGER* tmpser = BN_to_ASN1_INTEGER(serial, NULL);
BN_free(serial);
serial = NULL;
assert(tmpser != NULL);
i = X509_REVOKED_set_serialNumber(r, tmpser);
ASN1_INTEGER_free(tmpser);
X509_CRL_add0_revoked(x_crl, r);
return 0;
}
I have wrote above code and i got the serial number but do not get added to revoked list in "root_mod.crl" file.
Can you suggest any pointers ?

RSA_private_decrypt failed

I use openssl. First off I created private/public keys, then I encrypt a string and keep the result in a file. When I try to decrypt the file my program fails. What's more, the encrypted file is different each time(I use md5sum checked). What have I missed to deal with?
/*
gcc -lssl queation.c -o test_ssl
#openssl genrsa -out test_private.key 1024
#openssl rsa -in test_private.key -pubout -out test_public.key
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<openssl/rsa.h>
#include<openssl/pem.h>
#include<openssl/err.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/netdevice.h>
#include <linux/sockios.h>
#include <linux/if.h>
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if_arp.h>
#include <netinet/if_ether.h>
#include <netinet/ether.h>
#include <fcntl.h>
#include <sys/socket.h>
#define OPENSSLKEY "test_private.key"
#define PUBLICKEY "test_public.key"
#define BUFFSIZE 1024
#define SIZE 1024
#define LIC_FILE "lic.rn"
#define PRTFL printf("fun = %s, line = %d\n", __FUNCTION__,__LINE__)
static char *ptr_en;
static char *p_en;
static RSA *p_rsa_public;
static FILE *fp_public;
static int flen_public, rsa_public_len;
static char *ptr_de;
static char *p_de;
static RSA *p_rsa_private;
static FILE *fp_private;
static int flen_private, rsa_private_len;
void usage( unsigned char * prog_name)
{
printf("usage: %s\n",
prog_name);
exit(1);
}
int main(int argc , char ** argv)
{
int i, ret , len;
unsigned char buf_plain[32];
unsigned char *buf_en;
unsigned char *raw_buffer;
FILE * pf_tmp;
if( argc != 1)
{
usage(argv[0]);
}
snprintf(buf_plain,sizeof(buf_plain),"this is a test line.\n");
if((fp_public=fopen(PUBLICKEY,"r"))==NULL)
{
perror("open public key file error");
ret = -1;
goto error;
}
if((p_rsa_public = PEM_read_RSA_PUBKEY(fp_public,NULL,NULL,NULL))==NULL)
{
ERR_print_errors_fp(stdout);
ret = -1;
goto error;
}
rsa_public_len=RSA_size(p_rsa_public);
p_en=(unsigned char *)malloc(rsa_public_len+1);
memset(p_en,0,rsa_public_len+1);
//printf("%s(%d)p_en = %p,rsa_public_len = %d\n", __FUNCTION__,__LINE__,p_en,rsa_public_len);
len = RSA_public_encrypt(rsa_public_len,buf_plain,p_en,p_rsa_public,RSA_NO_PADDING);
if (len !=rsa_public_len)
{
fprintf(stderr,"Error: len =%d, rsa_public_len = %d,ciphertext should match length of key\n", len,rsa_public_len);
ret = -1;
goto error;
}
pf_tmp = fopen(LIC_FILE,"w");
if( NULL == pf_tmp )
{
printf("open %s failed\n",LIC_FILE);
ret = -1;
goto error;
}
fwrite(p_en,1,128,pf_tmp);
fclose(pf_tmp);
if((fp_private=fopen(OPENSSLKEY,"r"))==NULL)
{
perror("open private key file error");
ret = -1;
goto error;
}
if((p_rsa_private=PEM_read_RSAPrivateKey(fp_private,NULL,NULL,NULL))==NULL)
{
ERR_print_errors_fp(stdout);
ret = -1;
goto error;
}
rsa_private_len = RSA_size(p_rsa_private);
pf_tmp = fopen(LIC_FILE,"r");
if( NULL == pf_tmp )
{
printf("open %s failed\n",LIC_FILE);
ret = -1;
goto error2;
}
raw_buffer = calloc(rsa_private_len,sizeof(char));
if( NULL == raw_buffer )
{
ret = -1;
goto error;
}
len = fread(raw_buffer, sizeof(char),sizeof(raw_buffer), pf_tmp);
if( len <=0 )
{
ret = -1;
goto error;
}
p_de=(unsigned char *)malloc(rsa_private_len+1);
memset(p_de,0,rsa_private_len+1);
//printf("%s(%d)p_en = %p,rsa_public_len = %d\n", __FUNCTION__,__LINE__,p_en,rsa_public_len);
len =RSA_private_decrypt (rsa_private_len,raw_buffer,p_de,p_rsa_private,RSA_NO_PADDING);
printf("%s(%d) p_de = %s\n",__FUNCTION__,__LINE__,p_de);
if ( len != rsa_private_len )
{
fprintf(stderr,"Error: ciphertext should match length of key\n");
exit(1);
}
error2:
fclose(pf_tmp);
error:
free(ptr_en);
free(ptr_de);
fclose(fp_public);
fclose(fp_private);
RSA_free(p_rsa_public);
RSA_free(p_rsa_private);
return ret;
}
It looks like you are not reading the whole file:
len = fread(raw_buffer, sizeof(char),sizeof(raw_buffer), pf_tmp);
Note that sizeof(raw_buffer) is the size of a pointer, but you wrote 128 bytes into the file (1024 bits). So you're only reading back 4 or 8 bytes and trying to decrypt that.
Try reading 128 bytes back.

Resources