Exemplo n.º 1
0
static int
ccn_parse_Signature(struct ccn_buf_decoder *d, struct ccn_parsed_ContentObject *x)
{
    int res = -1;
    int i;
    struct ccn_parsed_ContentObject dummy;
    if (x == NULL)
        x = &dummy;
    for (i = CCN_PCO_B_Signature; i <= CCN_PCO_E_Signature; i++) {
        x->offset[i] = d->decoder.token_index;
    }
    if (ccn_buf_match_dtag(d, CCN_DTAG_Signature)) {
        res = d->decoder.element_index;
        ccn_buf_advance(d);
        x->offset[CCN_PCO_B_DigestAlgorithm] = d->decoder.token_index;
        ccn_parse_optional_tagged_UDATA(d, CCN_DTAG_DigestAlgorithm);
        x->offset[CCN_PCO_E_DigestAlgorithm] = d->decoder.token_index;
        x->offset[CCN_PCO_B_Witness] = d->decoder.token_index;
        ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Witness, 8, -1);
        x->offset[CCN_PCO_E_Witness] = d->decoder.token_index;
        x->offset[CCN_PCO_B_SignatureBits] = d->decoder.token_index;
        ccn_parse_required_tagged_BLOB(d, CCN_DTAG_SignatureBits, 16, -1);
        x->offset[CCN_PCO_E_SignatureBits] = d->decoder.token_index;
        ccn_buf_check_close(d);
        x->offset[CCN_PCO_E_Signature] = d->decoder.token_index;
    }
    if (d->decoder.state < 0)
        return (d->decoder.state);
    return(res);
}
Exemplo n.º 2
0
int
ccn_parse_ContentObject(const unsigned char *msg, size_t size,
                        struct ccn_parsed_ContentObject *x,
                        struct ccn_indexbuf *components)
{
    struct ccn_buf_decoder decoder;
    struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, msg, size);
    int res;
    x->magic = 20090415;
    x->digest_bytes = 0;
    if (ccn_buf_match_dtag(d, CCN_DTAG_ContentObject)) {
        ccn_buf_advance(d);
        res = ccn_parse_Signature(d, x);
        x->offset[CCN_PCO_B_Name] = d->decoder.token_index;
        x->offset[CCN_PCO_B_Component0] = d->decoder.index;
        res = ccn_parse_Name(d, components);
        if (res < 0)
            d->decoder.state = -__LINE__;
        x->name_ncomps = res;
        x->offset[CCN_PCO_E_ComponentLast] = d->decoder.token_index - 1;
        x->offset[CCN_PCO_E_Name] = d->decoder.token_index;
        ccn_parse_SignedInfo(d, x);
        x->offset[CCN_PCO_B_Content] = d->decoder.token_index;
        ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Content, 0, -1);
        x->offset[CCN_PCO_E_Content] = d->decoder.token_index;
        ccn_buf_check_close(d);
        x->offset[CCN_PCO_E] = d->decoder.index;
    }
    else
        d->decoder.state = -__LINE__;
    if (d->decoder.index != size || !CCN_FINAL_DSTATE(d->decoder.state))
        return (CCN_DSTATE_ERR_CODING);
    return(0);
}
Exemplo n.º 3
0
int
ccn_parse_optional_tagged_BLOB(struct ccn_buf_decoder *d, enum ccn_dtag dtag,
                               int minlen, int maxlen)
{
    if (ccn_buf_match_dtag(d, dtag))
        return(ccn_parse_required_tagged_BLOB(d, dtag, minlen, maxlen));
    return(-1);
}
Exemplo n.º 4
0
int
ccn_parse_Exclude(struct ccn_buf_decoder *d)
{
    int res = -1;
    if (ccn_buf_match_dtag(d, CCN_DTAG_Exclude)) {
        res = d->decoder.element_index;
        ccn_buf_advance(d);
        ccn_parse_optional_Any_or_Bloom(d);
        while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
            ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Component, 0, -1);
            ccn_parse_optional_Any_or_Bloom(d);
        }
        ccn_buf_check_close(d);
    }
    if (d->decoder.state < 0)
        return (d->decoder.state);
    return(res);
}
Exemplo n.º 5
0
PyObject *
Signature_obj_from_ccn(PyObject *py_signature)
{
	struct ccn_charbuf *signature;
	PyObject *py_obj_signature, *py_o;
	struct ccn_buf_decoder decoder, *d;
	size_t start, stop, size;
	const unsigned char *ptr;
	int r;

	assert(CCNObject_IsValid(SIGNATURE, py_signature));
	signature = CCNObject_Get(SIGNATURE, py_signature);

	debug("Signature_from_ccn start, len=%zd\n", signature->length);

	// 1) Create python object
	py_obj_signature = PyObject_CallObject(g_type_Signature, NULL);
	if (!py_obj_signature)
		return NULL;

	// 2) Set ccn_data to a cobject pointing to the c struct
	//    and ensure proper destructor is set up for the c object.
	r = PyObject_SetAttrString(py_obj_signature, "ccn_data", py_signature);
	JUMP_IF_NEG(r, error);

	// 3) Parse c structure and fill python attributes

	// Neither DigestAlgorithm nor Witness are included in the packet
	// from ccnput, so they are apparently both optional
	d = ccn_buf_decoder_start(&decoder, signature->buf, signature->length);

	if (!ccn_buf_match_dtag(d, CCN_DTAG_Signature)) {
		PyErr_Format(g_PyExc_CCNSignatureError, "Error finding"
				" CCN_DTAG_Signature (decoder state: %d)", d->decoder.state);
		goto error;
	}

	debug("Is a signature\n");
	ccn_buf_advance(d);

	/* CCN_DTAG_DigestAlgorithm */
	start = d->decoder.token_index;
	ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_DigestAlgorithm, 1, -1);
	stop = d->decoder.token_index;

	r = ccn_ref_tagged_BLOB(CCN_DTAG_DigestAlgorithm, d->buf, start, stop,
			&ptr, &size);
	if (r == 0) {
		debug("PyObject_SetAttrString digestAlgorithm\n");
		py_o = PyBytes_FromStringAndSize((const char*) ptr, size);
		JUMP_IF_NULL(py_o, error);
		r = PyObject_SetAttrString(py_obj_signature, "digestAlgorithm", py_o);
		Py_DECREF(py_o);
		JUMP_IF_NEG(r, error);
	}

	/* CCN_DTAG_Witness */
	start = d->decoder.token_index;
	ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Witness, 1, -1);
	stop = d->decoder.token_index;
	debug("witness start %zd stop %zd\n", start, stop);

	r = ccn_ref_tagged_BLOB(CCN_DTAG_Witness, d->buf, start, stop, &ptr, &size);
	if (r == 0) {
		// The Witness is represented as a DER-encoded PKCS#1 DigestInfo,
		// which contains an AlgorithmIdentifier (an OID, together with any necessary parameters)
		// and a byte array (OCTET STRING) containing the digest information to be interpreted according to that OID.
		// http://www.ccnx.org/releases/latest/doc/technical/SignatureGeneration.html
		debug("PyObject_SetAttrString witness\n");
		py_o = PyBytes_FromStringAndSize((const char*) ptr, size);
		JUMP_IF_NULL(py_o, error);
		r = PyObject_SetAttrString(py_obj_signature, "witness", py_o);
		Py_DECREF(py_o);
		JUMP_IF_NEG(r, error);
	}

	/* CCN_DTAG_SignatureBits */
	start = d->decoder.token_index;
	ccn_parse_required_tagged_BLOB(d, CCN_DTAG_SignatureBits, 1, -1);
	stop = d->decoder.token_index;

	r = ccn_ref_tagged_BLOB(CCN_DTAG_SignatureBits, d->buf, start, stop, &ptr,
			&size);
	if (r < 0) {
		PyErr_Format(g_PyExc_CCNSignatureError, "Error parsing"
				" CCN_DTAG_SignatureBits (decoder state %d)", d->decoder.state);
		goto error;
	}

	assert(r == 0);
	debug("PyObject_SetAttrString signatureBits\n");
	py_o = PyBytes_FromStringAndSize((const char*) ptr, size);
	JUMP_IF_NULL(py_o, error);
	r = PyObject_SetAttrString(py_obj_signature, "signatureBits", py_o);
	Py_DECREF(py_o);
	JUMP_IF_NEG(r, error);

	ccn_buf_check_close(d);
	if (d->decoder.state < 0) {
		PyErr_Format(g_PyExc_CCNSignatureError, "Signature decoding error"
				" (decoder state: %d, numval: %zd)", d->decoder.state,
				d->decoder.numval);
		goto error;
	}

	// 4) Return the created object
	debug("Signature_from_ccn ends\n");
	return py_obj_signature;

error:
	Py_DECREF(py_obj_signature);
	return NULL;
}
Exemplo n.º 6
0
static int
ccn_parse_SignedInfo(struct ccn_buf_decoder *d, struct ccn_parsed_ContentObject *x)
{
    x->offset[CCN_PCO_B_SignedInfo] = d->decoder.token_index;
    if (ccn_buf_match_dtag(d, CCN_DTAG_SignedInfo)) {
        ccn_buf_advance(d);
        x->offset[CCN_PCO_B_PublisherPublicKeyDigest] = d->decoder.token_index;
        ccn_parse_required_tagged_BLOB(d, CCN_DTAG_PublisherPublicKeyDigest, 16, 64);
        x->offset[CCN_PCO_E_PublisherPublicKeyDigest] = d->decoder.token_index;
        
        x->offset[CCN_PCO_B_Timestamp] = d->decoder.token_index;
        ccn_parse_required_tagged_timestamp(d, CCN_DTAG_Timestamp);
        x->offset[CCN_PCO_E_Timestamp] = d->decoder.token_index;
        
        x->offset[CCN_PCO_B_Type] = d->decoder.token_index;
        x->type = CCN_CONTENT_DATA;
        x->type = ccn_parse_optional_tagged_binary_number(d, CCN_DTAG_Type, 3, 3, CCN_CONTENT_DATA);
        x->offset[CCN_PCO_E_Type] = d->decoder.token_index;
        
        x->offset[CCN_PCO_B_FreshnessSeconds] = d->decoder.token_index;
        ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_FreshnessSeconds);
        x->offset[CCN_PCO_E_FreshnessSeconds] = d->decoder.token_index;
        
        x->offset[CCN_PCO_B_FinalBlockID] = d->decoder.token_index;
        ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_FinalBlockID, 1, -1);
        x->offset[CCN_PCO_E_FinalBlockID] = d->decoder.token_index;
        
        x->offset[CCN_PCO_B_KeyLocator] = d->decoder.token_index;
        x->offset[CCN_PCO_B_Key_Certificate_KeyName] = d->decoder.token_index;
        x->offset[CCN_PCO_E_Key_Certificate_KeyName] = d->decoder.token_index;
        x->offset[CCN_PCO_B_KeyName_Name] = d->decoder.token_index;
        x->offset[CCN_PCO_E_KeyName_Name] = d->decoder.token_index;
        x->offset[CCN_PCO_B_KeyName_Pub] = d->decoder.token_index;
        x->offset[CCN_PCO_E_KeyName_Pub] = d->decoder.token_index;
        if (ccn_buf_match_dtag(d, CCN_DTAG_KeyLocator)) {
            ccn_buf_advance(d);
            x->offset[CCN_PCO_B_Key_Certificate_KeyName] = d->decoder.token_index;
            if (ccn_buf_match_dtag(d, CCN_DTAG_Key)) {
                (void)ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Key, 0, -1);
            }
            else if (ccn_buf_match_dtag(d, CCN_DTAG_Certificate)) {
                (void)ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Certificate, 0, -1);
            }
            else {
                struct parsed_KeyName keyname = {-1, -1, -1, -1};
                if (ccn_parse_KeyName(d, &keyname) >= 0) {
                    if (keyname.Name >= 0) {
                        x->offset[CCN_PCO_B_KeyName_Name] = keyname.Name;
                        x->offset[CCN_PCO_E_KeyName_Name] = keyname.endName;
                    }
                    if (keyname.PublisherID >= 0) {
                        x->offset[CCN_PCO_B_KeyName_Pub] = keyname.PublisherID;
                        x->offset[CCN_PCO_E_KeyName_Pub] = keyname.endPublisherID;
                    }
                }
            }
            x->offset[CCN_PCO_E_Key_Certificate_KeyName] = d->decoder.token_index;
            ccn_buf_check_close(d);
        }
        x->offset[CCN_PCO_E_KeyLocator] = d->decoder.token_index;
        ccn_buf_check_close(d);
    }
    else
        d->decoder.state = -__LINE__;
    x->offset[CCN_PCO_E_SignedInfo] = d->decoder.token_index;
    if (d->decoder.state < 0)
        return (d->decoder.state);
    return(0);
}
Exemplo n.º 7
0
static PyObject *
ExclusionFilter_obj_from_ccn(PyObject *py_exclusion_filter)
{
	PyObject *py_obj_ExclusionFilter, *py_components = NULL;
	PyObject *py_o;
	struct ccn_charbuf *exclusion_filter;
	int r;
	struct ccn_buf_decoder decoder, *d;
	size_t start, stop;

	assert(g_type_ExclusionFilter);

	debug("ExclusionFilter_from_ccn start\n");

	exclusion_filter = CCNObject_Get(EXCLUSION_FILTER, py_exclusion_filter);

	// 1) Create python object
	py_obj_ExclusionFilter = PyObject_CallObject(g_type_ExclusionFilter, NULL);
	JUMP_IF_NULL(py_obj_ExclusionFilter, error);

	// 2) Set ccn_data to a cobject pointing to the c struct
	//    and ensure proper destructor is set up for the c object.
	r = PyObject_SetAttrString(py_obj_ExclusionFilter, "ccn_data",
			py_exclusion_filter);
	JUMP_IF_NEG(r, error);

	// 3) Parse c structure and fill python attributes
	//    using PyObject_SetAttrString
	//
	//    self.components = None
	//    # pyccn
	//    self.ccn_data_dirty = False
	//    self.ccn_data = None  # backing charbuf

	py_components = PyList_New(0);
	JUMP_IF_NULL(py_components, error);

	r = PyObject_SetAttrString(py_obj_ExclusionFilter, "components",
			py_components);
	JUMP_IF_NEG(r, error);

	/* begin the actual parsing */
	d = ccn_buf_decoder_start(&decoder, exclusion_filter->buf,
			exclusion_filter->length);

	r = ccn_buf_match_dtag(d, CCN_DTAG_Exclude);
	JUMP_IF_NEG(r, parse_error);
	ccn_buf_advance(d);

	r = ccn_buf_match_dtag(d, CCN_DTAG_Any);
	JUMP_IF_NEG(r, error);
	if (r) {
		ccn_buf_advance(d);
		ccn_buf_check_close(d);
		debug("got any: %d\n", r);

		py_o = Exclusion_Any_Obj();
		JUMP_IF_NULL(py_o, error);

		r = PyList_Append(py_components, py_o);
		Py_DECREF(py_o);
		JUMP_IF_NEG(r, error);
	}

	while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) {
		start = d->decoder.token_index;
		r = ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Component, 0, -1);
		JUMP_IF_NEG(r, error);
		stop = d->decoder.token_index;
		debug("got name\n");

		py_o = Exclusion_Name_Obj(exclusion_filter->buf, start, stop);
		r = PyList_Append(py_components, py_o);
		Py_DECREF(py_o);
		JUMP_IF_NEG(r, error);

		r = ccn_buf_match_dtag(d, CCN_DTAG_Any);
		if (r) {
			ccn_buf_advance(d);
			ccn_buf_check_close(d);
			debug("got *any*: %d\n", r);

			py_o = Exclusion_Any_Obj();
			JUMP_IF_NULL(py_o, error);

			r = PyList_Append(py_components, py_o);
			Py_DECREF(py_o);
			JUMP_IF_NEG(r, error);
		}
	}
	ccn_buf_check_close(d);
	JUMP_IF_NEG(d->decoder.state, parse_error);

	// 4) Return the created object
	debug("ExclusionFilter_from_ccn ends\n");

	return py_obj_ExclusionFilter;

parse_error:
	PyErr_SetString(g_PyExc_CCNExclusionFilterError, "error parsing the data");
error:
	Py_XDECREF(py_components);
	Py_XDECREF(py_obj_ExclusionFilter);
	return NULL;
}
Exemplo n.º 8
0
PyObject *
SignedInfo_obj_from_ccn(PyObject *py_signed_info)
{
	struct ccn_charbuf *signed_info;
	PyObject *py_obj_SignedInfo, *py_o;
	struct ccn_buf_decoder decoder, *d;
	size_t start, stop, size;
	const unsigned char *ptr;
	int r;

	signed_info = CCNObject_Get(SIGNED_INFO, py_signed_info);

	debug("SignedInfo_from_ccn start, size=%zd\n", signed_info->length);

	// 1) Create python object
	py_obj_SignedInfo = PyObject_CallObject(g_type_SignedInfo, NULL);
	if (!py_obj_SignedInfo)
		return NULL;

	// 2) Set ccn_data to a cobject pointing to the c struct
	//    and ensure proper destructor is set up for the c object.
	r = PyObject_SetAttrString(py_obj_SignedInfo, "ccn_data", py_signed_info);
	JUMP_IF_NEG(r, error);

	// 3) Parse c structure and fill python attributes
	//    using PyObject_SetAttrString
	// based on chk_signing_params
	// from ccn_client.c
	//
	//outputs:

	// Note, it is ok that non-filled optional elements
	// are initialized to None (through the .py file __init__)
	//

	d = ccn_buf_decoder_start(&decoder, signed_info->buf, signed_info->length);

	if (!ccn_buf_match_dtag(d, CCN_DTAG_SignedInfo)) {
		PyErr_Format(g_PyExc_CCNSignedInfoError, "Error finding"
				" CCN_DTAG_SignedInfo (decoder state: %d)", d->decoder.state);
		goto error;
	}

	ccn_buf_advance(d);

	/* PublisherPublic Key */
	//XXX: should we check for case when PublishePublicKeyDigest is not present? -dk
	start = d->decoder.token_index;
	ccn_parse_required_tagged_BLOB(d, CCN_DTAG_PublisherPublicKeyDigest,
			16, 64);
	stop = d->decoder.token_index;

	r = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, d->buf, start,
			stop, &ptr, &size);
	if (r < 0) {
		PyErr_Format(g_PyExc_CCNSignedInfoError, "Error parsing"
				" CCN_DTAG_PublisherPublicKey (decoder state %d)",
				d->decoder.state);
		goto error;
	}

	//    self.publisherPublicKeyDigest = None     # SHA256 hash
	debug("PyObject_SetAttrString publisherPublicKeyDigest\n");
	py_o = PyBytes_FromStringAndSize((const char*) ptr, size);
	JUMP_IF_NULL(py_o, error);
	r = PyObject_SetAttrString(py_obj_SignedInfo, "publisherPublicKeyDigest",
			py_o);
	Py_DECREF(py_o);
	JUMP_IF_NEG(r, error);

	/* Timestamp */
	start = d->decoder.token_index;
	ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Timestamp, 1, -1);
	stop = d->decoder.token_index;

	r = ccn_ref_tagged_BLOB(CCN_DTAG_Timestamp, d->buf, start, stop, &ptr,
			&size);
	if (r < 0) {
		PyErr_Format(g_PyExc_CCNSignedInfoError, "Error parsing"
				" CCN_DTAG_Timestamp (decoder state %d)", d->decoder.state);
		goto error;
	}

	//    self.timeStamp = None   # CCNx timestamp
	debug("PyObject_SetAttrString timeStamp\n");
	py_o = PyBytes_FromStringAndSize((const char*) ptr, size);
	JUMP_IF_NULL(py_o, error);
	r = PyObject_SetAttrString(py_obj_SignedInfo, "timeStamp", py_o);
	Py_DECREF(py_o);
	JUMP_IF_NEG(r, error);

	/* Type */
	assert(d->decoder.state >= 0);
	r = ccn_parse_optional_tagged_binary_number(d, CCN_DTAG_Type, 3, 3,
			CCN_CONTENT_DATA);
	if (d->decoder.state < 0) {
		PyErr_SetString(g_PyExc_CCNSignedInfoError, "Unable to parse type");
		goto error;
	}

	py_o = _pyccn_Int_FromLong(r);
	JUMP_IF_NULL(py_o, error);
	r = PyObject_SetAttrString(py_obj_SignedInfo, "type", py_o);
	Py_DECREF(py_o);
	JUMP_IF_NEG(r, error);

	/*
		start = d->decoder.token_index;
		ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Type, 1, -1);
		stop = d->decoder.token_index;

		r = ccn_ref_tagged_BLOB(CCN_DTAG_Type, d->buf, start, stop, &ptr, &size);
		if (r == 0) {
			//    type = None   # CCNx type
			// TODO: Provide a string representation with the Base64 mnemonic?
			debug("PyObject_SetAttrString type\n");
			py_o = PyByteArray_FromStringAndSize((const char*) ptr, size);
			JUMP_IF_NULL(py_o, error);
			r = PyObject_SetAttrString(py_obj_SignedInfo, "type", py_o);
			Py_DECREF(py_o);
			JUMP_IF_NEG(r, error);
		}
	 */

	/* FreshnessSeconds */
	r = ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_FreshnessSeconds);
	if (r >= 0) {
		//    self.freshnessSeconds = None
		debug("PyObject_SetAttrString freshnessSeconds\n");
		py_o = _pyccn_Int_FromLong(r);
		JUMP_IF_NULL(py_o, error);
		r = PyObject_SetAttrString(py_obj_SignedInfo, "freshnessSeconds", py_o);
		Py_DECREF(py_o);
		JUMP_IF_NEG(r, error);
	}

	/* FinalBlockID */
#if 0 /* old code (left in case mine is wrong - dk) */
	if (ccn_buf_match_dtag(d, CCN_DTAG_FinalBlockID)) {
		ccn_buf_advance(d);
		start = d->decoder.token_index;
		if (ccn_buf_match_some_blob(d))
			ccn_buf_advance(d);
		stop = d->decoder.token_index;
		ccn_buf_check_close(d);
		if (d->decoder.state >= 0 && stop > start) {
			//    self.finalBlockID = None
			fprintf(stderr, "PyObject_SetAttrString finalBlockID, len=%zd\n", stop - start);
			py_o = PyByteArray_FromStringAndSize((const char*) (d->buf + start), stop - start);
			PyObject_SetAttrString(py_obj_SignedInfo, "finalBlockID", py_o);
			Py_INCREF(py_o);
		}
	}
#endif
	start = d->decoder.token_index;
	ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_FinalBlockID, 1, -1);
	stop = d->decoder.token_index;

	r = ccn_ref_tagged_BLOB(CCN_DTAG_FinalBlockID, d->buf, start, stop, &ptr,
			&size);
	if (r == 0) {
		//    self.finalBlockID = None
		debug("PyObject_SetAttrString finalBlockID, len=%zd\n", size);
		py_o = PyBytes_FromStringAndSize((const char*) ptr, size);
		JUMP_IF_NULL(py_o, error);
		r = PyObject_SetAttrString(py_obj_SignedInfo, "finalBlockID", py_o);
		Py_DECREF(py_o);
		JUMP_IF_NEG(r, error);
	}

	/* KeyLocator */
#if 0 /* Old code in case mine is wrong - dk */
	start = d->decoder.token_index;
	if (ccn_buf_match_dtag(d, CCN_DTAG_KeyLocator))
		ccn_buf_advance_past_element(d);
	stop = d->decoder.token_index;
	if (d->decoder.state >= 0 && stop > start) {
		fprintf(stderr, "PyObject_SetAttrString keyLocator, len=%zd\n", stop - start);
		struct ccn_charbuf* keyLocator = ccn_charbuf_create();
		ccn_charbuf_append(keyLocator, d->buf + start, stop - start);
		//    self.keyLocator = None
		py_o = KeyLocator_obj_from_ccn(keyLocator); // it will free
		PyObject_SetAttrString(py_obj_SignedInfo, "keyLocator", py_o);
		Py_INCREF(py_o);
	}
#endif

	/*
	 * KeyLocator is not a BLOB, but an another structure, this requires
	 * us to parse it differently
	 */
	start = d->decoder.token_index;
	if (ccn_buf_match_dtag(d, CCN_DTAG_KeyLocator)) {
		struct ccn_charbuf *key_locator;
		PyObject *py_key_locator;

		r = ccn_buf_advance_past_element(d);
		if (r < 0) {
			PyErr_Format(g_PyExc_CCNSignedInfoError, "Error locating"
					" CCN_DTAG_KeyLocator (decoder state: %d, r: %d)",
					d->decoder.state, r);
			goto error;
		}
		stop = d->decoder.token_index;
		/*
				debug("element_index = %zd size = %zd nest = %d numval = %zd state = %d"
						" token_index %zd\n",
						d->decoder.element_index, d->decoder.index, d->decoder.nest,
						d->decoder.numval, d->decoder.state, d->decoder.token_index);
				assert(d->decoder.state >= 0);
		 */

		ptr = d->buf + start;
		size = stop - start;
		assert(size > 0);

		debug("PyObject_SetAttrString keyLocator, len=%zd\n", size);

		py_key_locator = CCNObject_New_charbuf(KEY_LOCATOR, &key_locator);
		JUMP_IF_NULL(py_key_locator, error);

		r = ccn_charbuf_append(key_locator, ptr, size);
		if (r < 0) {
			Py_DECREF(py_key_locator);
			PyErr_NoMemory();
			goto error;
		}

		//    self.keyLocator = None
		py_o = KeyLocator_obj_from_ccn(py_key_locator);
		Py_DECREF(py_key_locator);
		JUMP_IF_NULL(py_o, error);
		r = PyObject_SetAttrString(py_obj_SignedInfo, "keyLocator", py_o);
		Py_DECREF(py_o);
		JUMP_IF_NEG(r, error);
	}

	ccn_buf_check_close(d);
	if (d->decoder.state < 0) {
		PyErr_Format(g_PyExc_CCNSignedInfoError, "SignedInfo decoding error"
				" (decoder state: %d, numval: %zd)", d->decoder.state,
				d->decoder.numval);
		goto error;
	}

	// 4) Return the created object
	debug("SignedInfo_from_ccn ends\n");
	return py_obj_SignedInfo;

error:
	Py_DECREF(py_obj_SignedInfo);

	return NULL;
}