Using Xcode security framework to parse asn1 format - c

I'd like to parse asn1 format under OS-X 10.11.
Unfortunately, Apple doesn't include openssl as part of their SDK anymore. instead, there's an internal package I was advised to use exposed in the following header :
SDKs/MacOSX10.11.sdk/System/Library/Frameworks/Security.framework/Versions/A/Headers/SecAsn1Coder.h
Unfortunately, the API I needed to parse the asn1 file and extract a given field, seems very different from the original openssl API.
In openssl, the function "asn1parse" defined in include/openssl/asn1.h, gets a DER formatted file, decoding it and return output text that represent the asn1 tree.
In Apple implementation, I've found "SecAsn1Decode" that may provide the same functionality. The documentation says that the output argument (void *dest) is a pointer to "a template-specific struct allocated by the caller", but i don't understand what struct should I expect and how much memory should I allocate ?
perhaps you can help me understand how to use it. any references are welcome.

There are now several snippets on GitHub showing how to call the SecAsn1Decode function, see here for example:
typedef struct {
size_t length;
unsigned char *data;
} ASN1_Data;
typedef struct {
ASN1_Data type; // INTEGER
ASN1_Data version; // INTEGER
ASN1_Data value; // OCTET STRING
} RVNReceiptAttribute;
typedef struct {
RVNReceiptAttribute **attrs;
} RVNReceiptPayload;
// ASN.1 receipt attribute template
static const SecAsn1Template kReceiptAttributeTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RVNReceiptAttribute) },
{ SEC_ASN1_INTEGER, offsetof(RVNReceiptAttribute, type), NULL, 0 },
{ SEC_ASN1_INTEGER, offsetof(RVNReceiptAttribute, version), NULL, 0 },
{ SEC_ASN1_OCTET_STRING, offsetof(RVNReceiptAttribute, value), NULL, 0 },
{ 0, 0, NULL, 0 }
};
// ASN.1 receipt template set
static const SecAsn1Template kSetOfReceiptAttributeTemplate[] = {
{ SEC_ASN1_SET_OF, 0, kReceiptAttributeTemplate, sizeof(RVNReceiptPayload) },
{ 0, 0, NULL, 0 }
};
And later:
NSData *payloadData = …
RVNReceiptPayload payload = { NULL };
status = SecAsn1Decode(asn1Decoder, payloadData.bytes, payloadData.length, kSetOfReceiptAttributeTemplate, &payload);

Related

How to fill a global array of structures in c

this is the definition and declaration of the structure
typedef struct ST_accountsDB_t
{
float balance;
uint8_t primaryAccountNumber[20];
}ST_accountsDB_t;
ST_accountsDB_t accountsDB[255];
then I started filling it
accountsDB[0].balance = 20000;
accountsDB[0].primaryAccountNumber[20] = "1234567891234567";
accountsDB[1].balance = 50000;
accountsDB[1].primaryAccountNumber[20] = "9872653461728839";
accountsDB[2].balance = 40000;
accountsDB[2].primaryAccountNumber[20] = "6873645738467382";
accountsDB[3].balance = 28000;
accountsDB[3].primaryAccountNumber[20] = "3872634547838276";
accountsDB[4].balance = 3000;
accountsDB[4].primaryAccountNumber[20] = "1283764957873637";
accountsDB[5].balance = 100000;
accountsDB[5].primaryAccountNumber[20] = "3485793029384758";
accountsDB[6].balance = 30000;
accountsDB[6].primaryAccountNumber[20] = "8746330283748393";
this is the normal way to fill a string right ? why isn't it working ? am I missing something ?
You can initialize it when you declare it, using an initialization list.
ST_accountsDB_t accountsDB[255] = {
{20000, "1234567891234567"},
{50000, "9872653461728839"},
...
};
If you want to fill it in after declaring it, use strcpy() to copy strings.
strcpy(accountsDB[0].primaryAccountNumber, "1234567891234567");
Even though uint8_t is equivalent to unsigned char, it's conventional to use char arrays to declare strings.
typedef struct ST_accountsDB_t
{
float balance;
unsigned char primaryAccountNumber[20];
}ST_accountsDB_t;
If you initialize the variable:
ST_accountsDB_t accountsDB[255] = {
{ 20000.0, "1234567891234567", },
{ 50000.0, "9872653461728839", },
{ 40000.0, "6873645738467382", },
/* ...*/ };
In the code (but not initialization) using compound literals.
accountsDB[x] = (ST_accountsDB_t){ 40000.0, "6873645738467382", };
You cant assign arrays. You need to copy them yourself. If it is a string you need to use strcpy function.
strcpy(accountsDB[0].primaryAccountNumber,"1234567891234567");
As others have told you, use an initializer list. However, when doing so also consider using designated initializers to make the code safer and more readable:
ST_accountsDB_t accountsDB[] =
{
{ .balance = 20000, .primaryAccountNumber = "1234567891234567" },
{ .balance = 50000, .primaryAccountNumber = "9872653461728839" },
/* and so on */
};
You can also add a compile-time check to ensure data integrity:
#define ACCOUNTS_DB_SIZE 255
...
_Static_assert(sizeof accountsDB/sizeof accountsDB[0] == ACCOUNTS_DB_SIZE,
"Wrong size: accountsDB");
You want the compiler to fill-in a character array from a string. Don't make it difficult for everyone. Copy/paste/adapt is NOT the way to develop code.
typedef struct ST_accountsDB_t {
float balance;
char primaryAccountNumber[20]; // NB char, not uint8_t
} ST_accountsDB_t;
ST_accountsDB_t accountsDB[] = {
{ 20000.0, "1234567891234567", },
{ 50000.0, "9872653461728839", },
{ 40000.0, "6873645738467382", },
{ 28000.0, "3872634547838276", },
{ 3000.0, "1283764957873637", },
{ 100000.0, "3485793029384758", },
{ 30000.0, "8746330283748393", },
};
And, using the dimension 255 suggests you've spent the time counting... The compiler counts more accurately than most humans.

Building an ASN1 set using the openssl C API

I'm trying to build a set of sequences using the openssl C API. As was noted in various places, the documentation is VERY sparse on this and code samples seem to be non-existent.
I've found various suggestions on the web but none that seemed to work correctly.
I've gotten that far in order to create sequences:
#include <openssl/asn1t.h>
countdef struct StringStructure {
ASN1_INTEGER *count;
ASN1_INTEGER *asnVersion;
ASN1_OCTET_STRING *value;
} StringSequence;
DECLARE_ASN1_FUNCTIONS(StringSequence)
ASN1_SEQUENCE(StringSequence) = {
ASN1_SIMPLE(StringSequence, count, ASN1_INTEGER),
ASN1_SIMPLE(StringSequence, asnVersion, ASN1_INTEGER),
ASN1_SIMPLE(StringSequence, value, ASN1_OCTET_STRING),
} ASN1_SEQUENCE_END(StringSequence)
IMPLEMENT_ASN1_FUNCTIONS(StringSequence)
auto aSeq = StringSequence_new();
aSeq->count = ASN1_INTEGER_new();
aSeq->asnVersion = ASN1_INTEGER_new();
aSeq->value = ASN1_OCTET_STRING_new();
if (!ASN1_INTEGER_set(aSeq->count, 10) ||
!ASN1_INTEGER_set(aSeq->asnVersion, 1) ||
!ASN1_STRING_set(aSeq->value, "Test", -1)) {
// -- Error
}
auto anotherSeq = StringSequence_new();
anotherSeq->count = ASN1_INTEGER_new();
anotherSeq->asnVersion = ASN1_INTEGER_new();
anotherSeq->value = ASN1_OCTET_STRING_new();
if (!ASN1_INTEGER_set(anotherSeq->count, 32) ||
!ASN1_INTEGER_set(anotherSeq->asnVersion, 1) ||
!ASN1_STRING_set(anotherSeq->value, "Something Else", -1)) {
// -- Error
}
Where do I go from there in order to build a set of these?
The OpenSSL source code is your best documentation...
As an example of a construct like the one you are trying to build, check out the PKCS7_SIGNED ASN1 definition in crypto/pkcs7/pk7_asn1.c:
ASN1_NDEF_SEQUENCE(PKCS7_SIGNED) = {
ASN1_SIMPLE(PKCS7_SIGNED, version, ASN1_INTEGER),
ASN1_SET_OF(PKCS7_SIGNED, md_algs, X509_ALGOR),
ASN1_SIMPLE(PKCS7_SIGNED, contents, PKCS7),
ASN1_IMP_SEQUENCE_OF_OPT(PKCS7_SIGNED, cert, X509, 0),
ASN1_IMP_SET_OF_OPT(PKCS7_SIGNED, crl, X509_CRL, 1),
ASN1_SET_OF(PKCS7_SIGNED, signer_info, PKCS7_SIGNER_INFO)
} ASN1_NDEF_SEQUENCE_END(PKCS7_SIGNED)
Its second member, md_algs, is a set of X509_ALGOR, which is in itself a sequence defined in crypto/asn1/x_algor.c:
ASN1_SEQUENCE(X509_ALGOR) = {
ASN1_SIMPLE(X509_ALGOR, algorithm, ASN1_OBJECT),
ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY)
} ASN1_SEQUENCE_END(X509_ALGOR)
So that field md_algs is a set of sequences, like you are asking for. The equivalent C- structure definitions can be found in include/openssl/pkcs7.h:
typedef struct pkcs7_signed_st {
ASN1_INTEGER *version; /* version 1 */
STACK_OF(X509_ALGOR) *md_algs; /* md used */
STACK_OF(X509) *cert; /* [ 0 ] */
STACK_OF(X509_CRL) *crl; /* [ 1 ] */
STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
struct pkcs7_st *contents;
} PKCS7_SIGNED;
The md_algs field shows that to capture the set-construct, you need to use the STACK API, which is intended to handle collections. In your case, that would be a STACK_OF(StringSequence).

PHP Extension: Working with class objects

Let's say I'm creating a PHP 7 extension (in C, NOT C++ and I do not want answers that talk about PHP-CPP at all) and I want to make a php object like Dog and give it variables and functions in the extension itself.
Lets say we have a PHP class like this...
class Dog {
public name;
public age;
private color;
private function play_ball() {
echo $this->name . " is playing with a ball!";
}
public function get_color() {
$this->play_ball();
return $this->color;
}
}
How would someone do this in an extension written in C? Is this even possible?
I will give you an example of the class, but I'll drop this link to github because I think it'll give you a starting point from where you can get the rest of the information about how to create an extension
https://github.com/twigphp/Twig/blob/1.x/ext/twig/twig.c
And here is the class definition code, it's quite verbose and you can use macros and function calls to reduce the amount of boilerplate code, but I'm just trying to explain how to do it, not show you the ultimate, best way to do everything.
Please Note: I didnt compile this code, although I'm sure it's 99% accurate, maybe you'll have to fix up some small issues, just ask me if you have doubts.
// I won't include this file, but just look at the twig.c extension source code
// It's mostly boilerplate and you just copy and paste what you need
#include "php_myanimals.h"
// This is the "class entry" php will use to define your class
zend_class_entry *dog_ce;
#define DECLARE_MEMBER(type,name,value,access) \
type(dog_ce, name, strlen(name), value, access TSRMLS_CC)
#define DECLARE_STRING(name,value,access) \
DECLARE_MEMBER(zend_declare_property_string,name,value,access)
#define DECLARE_LONG(name,value,access) \
DECLARE_MEMBER(zend_declare_property_long,name,value,access)
#define SET_PARAM(name,value) \
zend_update_property(dog_ce, this_ptr, name, strlen(name), value TSRMLS_CC)
#define GET_PARAM(name) \
zend_read_property(dog_ce, this_ptr, name, strlen(name), 1 TSRMLS_CC)
/* {{{ Method: Dog::__construct() */
PHP_METHOD(dog, __construct)
{
zval *name = NULL;
zval *colour = NULL;
// First look in the parameter list for a server string
// The | means that all parameters afterwards, are optional
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &name, &colour) == FAILURE)
{
EX_INVALID_ARG("MyAnimals\\Dog::__construct(string name, [string colour]), parameters were not valid");
}
SET_PARAM("name",name);
SET_PARAM("colour",colour);
}
/* }}} */
/* {{{ Method: Dog::playBall) */
PHP_METHOD(dog, playBall)
{
php_printf("%s is playing with a ball!", Z_STRVAL_P(GET_PARAM("name")));
}
/* }}} */
/* {{{ Method: bool Dog::getColour() */
PHP_METHOD(dog, getColour)
{
// yeah, the stupid zend engine programmers made a function
// that can take 0, 1 or 2 arguments, but if you want 3 or 4 args?
// then you have to use this enormous chunk of boilerplate code
// see: https://github.com/twigphp/Twig/blob/1.x/ext/twig/twig.c
// search for: TWIG_CALL_USER_FUNC_ARRAY
// You probably should wrap up this ugly shit in a function call
// But I've copied it directly here because it's easier
zend_call_method(
&this_ptr, Z_OBJCE_P(this_ptr), NULL,
// CAREFUL! php methods are in lower case!!
"playball", strlen("playball"),
// this is zval *retval or NULL if you dont want a return value
NULL,
// means zero parameters
0,
// arg 1
NULL,
// arg 2
NULL
TSRMLS_CC
);
RETURN(GET_PARAM("colour"));
}
/* }}} */
ZEND_BEGIN_ARG_INFO_EX(arginfo_construct, 0, 0, 1)
ZEND_ARG_INFO(0, name)
ZEND_ARG_INFO(0, colour)
ZEND_END_ARG_INFO()
const zend_function_entry dog_functions[] = {
// public methods
PHP_ME(dog, __construct, arginfo_construct, ZEND_ACC_PUBLIC)
PHP_ME(dog, getColour, NULL, ZEND_ACC_PUBLIC)
// protected methods
PHP_ME(dog, playBall, arginfo_createmanager, ZEND_ACC_PROTECTED)
PHP_FE_END
};
/* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(MyAnimals)
{
zend_class_entry entry;
// Creates a class like this \MyAnimals\Dog
INIT_NS_CLASS_ENTRY(entry, "MyAnimals", "Dog", dog_functions);
dog_ce = zend_register_internal_class(&entry TSRMLS_CC);
// Declare the state / error properties
DECLARE_STRING("name", "", ZEND_ACC_PUBLIC);
DECLARE_LONG("age", 0, ZEND_ACC_PRIVATE);
DECLARE_STRING("colour", "", ZEND_ACC_PROTECTED);
return SUCCESS;
}
/* }}} */

Replacing deprecated "dev_attrs" attribute with "dev_groups"

I'm trying to compile a Linux device driver (kernel module), however the module was last updated in April 2013 and of course it doesn't compile anymore on a recent (3.13) kernel, here's the error :
als_sys.c:99:2: error: unknown field ‘dev_attrs’ specified in initializer
I've searched already but all that I found were patches, there is no clear "tutorial" about updating an old module, the only thing I understood was that I need to use dev_groups instead, but it doesn't accept the same value as dev_attrs and I don't know how to adapt the existing code for that.
The code (some of it, the entire code can be found here) :
# als_sys.c
static ssize_t
illuminance_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct als_device *als = to_als_device(dev);
int illuminance;
int result;
result = als->ops->get_illuminance(als, &illuminance);
if (result)
return result;
if (!illuminance)
return sprintf(buf, "0\n");
else if (illuminance == -1)
return sprintf(buf, "-1\n");
else if (illuminance < -1)
return -ERANGE;
else
return sprintf(buf, "%d\n", illuminance);
}
# truncated - also "adjustment_show" is similar to this function so
# I didn't copy/paste it to save some space in the question
static struct device_attribute als_attrs[] = { # that's what I need to modify, but
__ATTR(illuminance, 0444, illuminance_show, NULL), # I have no clue what to
__ATTR(display_adjustment, 0444, adjustment_show, NULL), # put here instead
__ATTR_NULL,
};
# truncated
static struct class als_class = {
.name = "als",
.dev_release = als_release,
.dev_attrs = als_attrs, # line 99, that's where it fails
};
EDIT
As mentioned in the answer below, I changed the code like this :
static struct device_attribute als_attrs[] = {
__ATTR(illuminance, 0444, illuminance_show, NULL),
__ATTR(display_adjustment, 0444, adjustment_show, NULL),
__ATTR_NULL,
};
static const struct attribute_group als_attr_group = {
.attrs = als_attrs,
};
static struct class als_class = {
.name = "als",
.dev_release = als_release,
.dev_groups = als_attr_group, # line 103 - it fails here again
};
But I still get another error :
als_sys.c:103:2: error: initializer element is not constant
I've found this question which is about the same error however its answer is about a single attribute and I don't know how to adapt it for multiple ones.
Thanks for your help and have a nice day.
Indeed, dev_attrs was replaced with dev_groups in 3.13. In 3.12 they were both presented in struct. Look at 3.12 version and 3.13 version.
Anyway, there should not be a problem, because simple search for attribute_group gives you a lot of examples.
Simply put, you have to embed your dev_attrs inside dev_group:
static const struct attribute_group als_attr_group = {
.attrs = als_attrs,
};
And then use that attribute group in struct class.
There is also a handy macro ATTRIBUTE_GROUPS. See example usage https://lkml.org/lkml/2013/10/23/218.
EDIT:
Remove const declaration from attribute group like this:
static struct attribute_group als_attr_group = {
.attrs = als_attrs,
};
Because you can't initialize const struct with something that is not literal like 0xff or 'c'. See more detailes here.

Mapping error code to error description

I would have preferred to add a comment to the answer to this question
but didn't have enough points. Consider the following code:
enum _config_error
{
E_SUCCESS = 0,
E_INVALID_INPUT = -1,
E_FILE_NOT_FOUND = -2, /* consider some way of returning the OS error too */
...
};
/* type to provide in your API */
typedef _config_error error_t;
/* use this to provide a perror style method to help consumers out */
struct _errordesc {
int code;
char *message;
} errordesc[] = {
{ E_SUCCESS, "No error" },
{ E_INVALID_INPUT, "Invalid input" },
{ E_FILE_NOT_FOUND, "File not found" },
...
};
How does one lookup the error description from errordesc? I can see two problems with the version I come up with:
/* add E_COUNT = 3 to enum _config_error */
const char *errorstring(error_t errnum)
{
unsigned int i;
for (i = 0; i < E_COUNT; ++i) {
if (errordesc[i].code == errnum) {
return errordesc[i].message;
}
}
return "Can't reach this point";
}
One does know the enum size and has to manually set E_COUNT to 3.
One cannot reach the return after the for loop, what to do there?
Is there a better solution?
You can calculate E_COUNT from sizeof(errordesc) / sizeof(struct _errordesc).
If you reach the end of the loop, simply return "Unknown error" or something similar.
Since your error codes seems to be consecutive (but negative) you could index directly into the array using -errnum.
A better option is to ensure all your error codes have successive values from 0 up (or down). Then you can use them as indices into errordesc[]. Of course, if they are negative, you would do something like errordesc[-errnum].
As for the number of entries in errordesc[], it's sizeof(errordesc)/sizeof(errordesc[0]). You can store it in a global variable.
There's also bsearch() in C...

Resources