예제 #1
0
struct ccn_parsed_interest *
_pyccn_interest_get_pi(PyObject *py_interest)
{
	struct interest_data *context;
	struct ccn_charbuf *interest;
	int r;

	assert(CCNObject_IsValid(INTEREST, py_interest));

	context = PyCapsule_GetContext(py_interest);
	assert(context);

	if (context->pi)
		return context->pi;

	interest = CCNObject_Get(INTEREST, py_interest);

	context->pi = calloc(1, sizeof(struct ccn_parsed_interest));
	JUMP_IF_NULL_MEM(context->pi, error);

	/* TODO: we should also use the comps argument */
	r = ccn_parse_interest(interest->buf, interest->length, context->pi, NULL);
	if (r < 0) {
		PyErr_SetString(g_PyExc_CCNInterestError, "Unable to parse the"
				" Interest");
		goto error;
	}

	assert(context->pi);
	return context->pi;

error:
	return NULL;

}
예제 #2
0
PyObject *
_pyccn_cmd_verify_signature(PyObject *UNUSED(self), PyObject *args)
{
    PyObject *py_content_object, *py_pub_key;
    PyObject *res;
    struct ccn_charbuf *content_object;
    struct ccn_parsed_ContentObject *pco;
    struct ccn_pkey *pub_key;
    int r;

    if (!PyArg_ParseTuple(args, "OO", &py_content_object, &py_pub_key))
        return NULL;

    if (!CCNObject_IsValid(CONTENT_OBJECT, py_content_object)) {
        PyErr_SetString(PyExc_TypeError, "argument 1 must be CCN"
                        " ContentObject");
        return NULL;
    }

    if (!CCNObject_IsValid(PKEY_PUB, py_pub_key)) {
        PyErr_SetString(PyExc_TypeError, "argument 2 must be CCN public key");
        return NULL;
    }

    content_object = CCNObject_Get(CONTENT_OBJECT, py_content_object);
    pco = _pyccn_content_object_get_pco(py_content_object);
    if (!pco)
        return NULL;

    pub_key = CCNObject_Get(PKEY_PUB, py_pub_key);

    r = ccn_verify_signature(content_object->buf, content_object->length, pco,
                             pub_key);
    if (r < 0) {
        PyErr_SetString(g_PyExc_CCNSignatureError, "error verifying signature");
        return NULL;
    }

    res = r ? Py_True : Py_False;

    return Py_INCREF(res), res;
}
예제 #3
0
PyObject *
_pyccn_cmd_content_matches_interest(PyObject *UNUSED(self), PyObject *args)
{
    PyObject *py_content_object, *py_interest;
    struct ccn_charbuf *content_object, *interest;
    struct ccn_parsed_ContentObject *pco;
    struct ccn_parsed_interest *pi;
    int r;
    PyObject *res;

    if (!PyArg_ParseTuple(args, "OO", &py_content_object, &py_interest))
        return NULL;

    if (!CCNObject_IsValid(CONTENT_OBJECT, py_content_object)) {
        PyErr_SetString(PyExc_TypeError, "Expected CCN ContentObject");
        return NULL;
    }

    if (!CCNObject_IsValid(INTEREST, py_interest)) {
        PyErr_SetString(PyExc_TypeError, "Expected CCN Interest");
        return NULL;
    }

    content_object = CCNObject_Get(CONTENT_OBJECT, py_content_object);
    interest = CCNObject_Get(INTEREST, py_interest);

    pco = _pyccn_content_object_get_pco(py_content_object);
    if (!pco)
        return NULL;

    pi = _pyccn_interest_get_pi(py_interest);
    if (!pi)
        return NULL;

    r = ccn_content_matches_interest(content_object->buf,
                                     content_object->length, 1, pco, interest->buf, interest->length,
                                     pi);

    res = r ? Py_True : Py_False;

    return Py_INCREF(res), res;
}
예제 #4
0
PyObject *
_pyccn_cmd_verify_content(PyObject *UNUSED(self), PyObject *args)
{
    PyObject *py_handle, *py_content_object;
    PyObject *res;
    struct ccn *handle;
    struct ccn_charbuf *content_object;
    struct ccn_parsed_ContentObject *pco;
    int r;

    if (!PyArg_ParseTuple(args, "OO", &py_handle, &py_content_object))
        return NULL;

    if (!CCNObject_IsValid(HANDLE, py_handle)) {
        PyErr_SetString(PyExc_TypeError, "argument 1 must be a CCN handle");
        return NULL;
    }

    if (!CCNObject_IsValid(CONTENT_OBJECT, py_content_object)) {
        PyErr_SetString(PyExc_TypeError, "argument 2 must be CCN"
                        " ContentObject");
        return NULL;
    }


    handle = CCNObject_Get(HANDLE, py_handle);
    content_object = CCNObject_Get(CONTENT_OBJECT, py_content_object);
    pco = _pyccn_content_object_get_pco(py_content_object);
    if (!pco)
        return NULL;

    assert(content_object->length == pco->offset[CCN_PCO_E]);

    r = ccn_verify_content(handle, content_object->buf, pco);

    res = r == 0 ? Py_True : Py_False;

    return Py_INCREF(res), res;
}
예제 #5
0
static PyObject *
Name_obj_from_ccn_parsed(PyObject *py_content_object)
{
    struct ccn_charbuf *content_object;
    struct ccn_parsed_ContentObject *parsed_content_object;
    PyObject *py_ccn_name;
    PyObject *py_Name;
    struct ccn_charbuf *name;
    size_t name_begin, name_end, s;
    int r;

    assert(CCNObject_IsValid(CONTENT_OBJECT, py_content_object));

    content_object = CCNObject_Get(CONTENT_OBJECT, py_content_object);
    parsed_content_object = _pyccn_content_object_get_pco(py_content_object);
    if (!parsed_content_object)
        return NULL;

    name_begin = parsed_content_object->offset[CCN_PCO_B_Name];
    name_end = parsed_content_object->offset[CCN_PCO_E_Name];
    s = name_end - name_begin;

    debug("ContentObject_from_ccn_parsed Name len=%zd\n", s);
    if (parsed_content_object->name_ncomps <= 0) {
        PyErr_SetString(g_PyExc_CCNNameError, "No name stored (or name is"
                        " invalid) in parsed content object");
        return NULL;
    }

    py_ccn_name = CCNObject_New_charbuf(NAME, &name);
    if (!py_ccn_name)
        return NULL;

    r = ccn_charbuf_append(name, &content_object->buf[name_begin], s);
    if (r < 0) {
        Py_DECREF(py_ccn_name);
        return PyErr_NoMemory();
    }

#if DEBUG_MSG
    debug("Name: ");
    dump_charbuf(name, stderr);
    debug("\n");
#endif

    py_Name = Name_obj_from_ccn(py_ccn_name);
    Py_DECREF(py_ccn_name);

    return py_Name;
}
예제 #6
0
static int
parse_ContentObject(PyObject *py_content_object)
{
    struct content_object_data *context;
    struct ccn_charbuf *content_object;
    int r;

    assert(CCNObject_IsValid(CONTENT_OBJECT, py_content_object));

    context = PyCapsule_GetContext(py_content_object);
    assert(context);
    if (context->pco)
        free(context->pco);
    ccn_indexbuf_destroy(&context->comps);

    /*
     * no error happens between deallocation and following line, so I'm not
     * setting context->pco to NULL
     */
    context->pco = calloc(1, sizeof(struct ccn_parsed_ContentObject));
    JUMP_IF_NULL_MEM(context->pco, error);

    context->comps = ccn_indexbuf_create();
    JUMP_IF_NULL_MEM(context->comps, error);

    content_object = CCNObject_Get(CONTENT_OBJECT, py_content_object);

    r = ccn_parse_ContentObject(content_object->buf, content_object->length,
                                context->pco, context->comps);
    if (r < 0) {
        PyErr_SetString(g_PyExc_CCNContentObjectError, "Unable to parse the"
                        " ContentObject");
        goto error;
    }

    return 0;
error:
    if (context->pco) {
        free(context->pco);
        context->pco = NULL;
    }
    ccn_indexbuf_destroy(&context->comps);
    return -1;
}
예제 #7
0
PyObject *
_pyccn_cmd_digest_contentobject(PyObject *UNUSED(self), PyObject *args)
{
    PyObject *py_content_object;
    struct ccn_charbuf *content_object;
    struct ccn_parsed_ContentObject *parsed_content_object;
    PyObject *py_digest;

    if (!PyArg_ParseTuple(args, "O", &py_content_object))
        return NULL;

    if (!CCNObject_IsValid(CONTENT_OBJECT, py_content_object)) {
        PyErr_SetString(PyExc_TypeError, "Expected CCN ContentObject");
        return NULL;
    }

    content_object = CCNObject_Get(CONTENT_OBJECT, py_content_object);
    parsed_content_object = _pyccn_content_object_get_pco(py_content_object);
    if (!parsed_content_object)
        return NULL;

    /*
     * sanity check (sigh, I guess pco and comps should be carried in
     * capsule's context, since they're very closely related)
     */
    if (content_object->length != parsed_content_object->offset[CCN_PCO_E]) {
        PyErr_SetString(PyExc_ValueError, "ContentObject size doesn't match"
                        " the size reported by pco");
        return NULL;
    }

    ccn_digest_ContentObject(content_object->buf, parsed_content_object);
    py_digest = PyBytes_FromStringAndSize(
                    (char *) parsed_content_object->digest,
                    parsed_content_object->digest_bytes);

    return py_digest;
}
예제 #8
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;
}
예제 #9
0
PyObject *
_pyccn_cmd_encode_ContentObject(PyObject *UNUSED(self), PyObject *args)
{
    PyObject *py_content_object, *py_name, *py_content, *py_signed_info,
             *py_key;
    PyObject *py_o = NULL, *ret = NULL;
    struct ccn_charbuf *name, *signed_info, *content_object = NULL;
    struct ccn_pkey *private_key;
    const char *digest_alg = NULL;
    char *content;
    Py_ssize_t content_len;
    int r;

    if (!PyArg_ParseTuple(args, "OOOOO", &py_content_object, &py_name,
                          &py_content, &py_signed_info, &py_key))
        return NULL;

    if (strcmp(py_content_object->ob_type->tp_name, "ContentObject")) {
        PyErr_SetString(PyExc_TypeError, "Must pass a ContentObject as arg 1");
        return NULL;
    }

    if (!CCNObject_IsValid(NAME, py_name)) {
        PyErr_SetString(PyExc_TypeError, "Must pass a CCN Name as arg 2");
        return NULL;
    } else
        name = CCNObject_Get(NAME, py_name);

    if (py_content != Py_None && !PyBytes_Check(py_content)) {
        PyErr_SetString(PyExc_TypeError, "Must pass a Bytes as arg 3");
        return NULL;
    } else if (py_content == Py_None) {
        content = NULL;
        content_len = 0;
    } else {
        r = PyBytes_AsStringAndSize(py_content, &content, &content_len);
        if (r < 0)
            return NULL;
    }

    if (!CCNObject_IsValid(SIGNED_INFO, py_signed_info)) {
        PyErr_SetString(PyExc_TypeError, "Must pass a CCN SignedInfo as arg 4");
        return NULL;
    } else
        signed_info = CCNObject_Get(SIGNED_INFO, py_signed_info);

    if (strcmp(py_key->ob_type->tp_name, "Key")) {
        PyErr_SetString(PyExc_TypeError, "Must pass a Key as arg 4");
        return NULL;
    }

    // DigestAlgorithm
    py_o = PyObject_GetAttrString(py_content_object, "digestAlgorithm");
    if (py_o != Py_None) {
        PyErr_SetString(PyExc_NotImplementedError, "non-default digest"
                        " algorithm not yet supported");
        goto error;
    }
    Py_CLEAR(py_o);

    // Key
    private_key = Key_to_ccn_private(py_key);

    // Note that we don't load this key into the keystore hashtable in the library
    // because it makes this method require access to a ccn handle, and in fact,
    // ccn_sign_content just uses what's in signedinfo (after an error check by
    // chk_signing_params and then calls ccn_encode_ContentObject anyway
    //
    // Encode the content object

    // Build the ContentObject here.
    content_object = ccn_charbuf_create();
    JUMP_IF_NULL_MEM(content_object, error);

    r = ccn_encode_ContentObject(content_object, name, signed_info, content,
                                 content_len, digest_alg, private_key);

    debug("ccn_encode_ContentObject res=%d\n", r);
    if (r < 0) {
        ccn_charbuf_destroy(&content_object);
        PyErr_SetString(g_PyExc_CCNError, "Unable to encode ContentObject");
        goto error;
    }

    ret = CCNObject_New(CONTENT_OBJECT, content_object);

error:
    Py_XDECREF(py_o);
    return ret;
}
예제 #10
0
PyObject *
ContentObject_obj_from_ccn(PyObject *py_content_object)
{
    struct ccn_charbuf *content_object;
    struct ccn_parsed_ContentObject *parsed_content_object;
    PyObject *py_obj_ContentObject, *py_o;
    int r;
    struct ccn_charbuf *signature;
    PyObject *py_signature;
    struct ccn_charbuf *signed_info;
    PyObject *py_signed_info;

    if (!CCNObject_ReqType(CONTENT_OBJECT, py_content_object))
        return NULL;

    content_object = CCNObject_Get(CONTENT_OBJECT, py_content_object);
    parsed_content_object = _pyccn_content_object_get_pco(py_content_object);
    if (!parsed_content_object)
        return NULL;

    debug("ContentObject_from_ccn_parsed content_object->length=%zd\n",
          content_object->length);

    py_obj_ContentObject = PyObject_CallObject(g_type_ContentObject, NULL);
    if (!py_obj_ContentObject)
        return NULL;

    /* Name */
    py_o = Name_obj_from_ccn_parsed(py_content_object);
    JUMP_IF_NULL(py_o, error);
    r = PyObject_SetAttrString(py_obj_ContentObject, "name", py_o);
    Py_DECREF(py_o);
    JUMP_IF_NEG(r, error);

    /* Content */
    py_o = Content_from_ccn_parsed(content_object, parsed_content_object);
    JUMP_IF_NULL(py_o, error);
    r = PyObject_SetAttrString(py_obj_ContentObject, "content", py_o);
    Py_DECREF(py_o);
    JUMP_IF_NEG(r, error);

    /* Signature */
    debug("ContentObject_from_ccn_parsed Signature\n");
    py_signature = CCNObject_New_charbuf(SIGNATURE, &signature);
    JUMP_IF_NULL(py_signature, error);
    r = ccn_charbuf_append(signature,
                           &content_object->buf[parsed_content_object->offset[CCN_PCO_B_Signature]],
                           (size_t) (parsed_content_object->offset[CCN_PCO_E_Signature]
                                     - parsed_content_object->offset[CCN_PCO_B_Signature]));
    if (r < 0) {
        PyErr_NoMemory();
        Py_DECREF(py_signature);
        goto error;
    }

    py_o = Signature_obj_from_ccn(py_signature);
    Py_DECREF(py_signature);
    JUMP_IF_NULL(py_o, error);
    r = PyObject_SetAttrString(py_obj_ContentObject, "signature", py_o);
    Py_DECREF(py_o);
    JUMP_IF_NEG(r, error);

    debug("ContentObject_from_ccn_parsed SignedInfo\n");

    py_signed_info = CCNObject_New_charbuf(SIGNED_INFO, &signed_info);
    JUMP_IF_NULL(py_signed_info, error);

    r = ccn_charbuf_append(signed_info,
                           &content_object->buf[parsed_content_object->offset[CCN_PCO_B_SignedInfo]],
                           (size_t) (parsed_content_object->offset[CCN_PCO_E_SignedInfo]
                                     - parsed_content_object->offset[CCN_PCO_B_SignedInfo]));
    if (r < 0) {
        PyErr_NoMemory();
        Py_DECREF(py_signed_info);
        goto error;
    }

    py_o = SignedInfo_obj_from_ccn(py_signed_info);
    Py_DECREF(py_signed_info);
    JUMP_IF_NULL(py_o, error);
    r = PyObject_SetAttrString(py_obj_ContentObject, "signedInfo", py_o);
    Py_DECREF(py_o);
    JUMP_IF_NEG(r, error);

    debug("ContentObject_from_ccn_parsed DigestAlgorithm\n");
    // TODO...  Note this seems to default to nothing in the library...?
    r = PyObject_SetAttrString(py_obj_ContentObject, "digestAlgorithm", Py_None);
    JUMP_IF_NEG(r, error);

    /* Original data  */
    debug("ContentObject_from_ccn_parsed ccn_data\n");
    r = PyObject_SetAttrString(py_obj_ContentObject, "ccn_data", py_content_object);
    JUMP_IF_NEG(r, error);

    r = PyObject_SetAttrString(py_obj_ContentObject, "ccn_data_dirty", Py_False);
    JUMP_IF_NEG(r, error);

    debug("ContentObject_from_ccn_parsed complete\n");

    return py_obj_ContentObject;

error:
    Py_XDECREF(py_obj_ContentObject);
    return NULL;
}
예제 #11
0
PyObject *
Interest_obj_from_ccn(PyObject *py_interest)
{
	struct ccn_charbuf *interest;
	struct ccn_parsed_interest *pi;
	PyObject *py_obj_Interest, *py_o;
	int r;

	debug("Interest_from_ccn_parsed start\n");

	interest = CCNObject_Get(INTEREST, py_interest);

	// 1) Create python object
	py_obj_Interest = PyObject_CallObject(g_type_Interest, NULL);
	if (!py_obj_Interest)
		return NULL;

	pi = _pyccn_interest_get_pi(py_interest);
	JUMP_IF_NULL(pi, 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_Interest, "ccn_data", py_interest);
	JUMP_IF_NEG(r, error);

	// 3) Parse c structure and fill python attributes
	//    using PyObject_SetAttrString

	ssize_t len;
	const unsigned char *blob;
	size_t blob_size, start, end;
	struct ccn_charbuf * cb;

	// Best decoding examples are in packet-ccn.c for wireshark plugin?

	//        self.name = None  # Start from None to use for templates?
	len = pi->offset[CCN_PI_E_Name] - pi->offset[CCN_PI_B_Name];
	if (len > 0) {
		PyObject *py_cname;

		py_cname = CCNObject_New_charbuf(NAME, &cb);
		JUMP_IF_NULL(py_cname, error);

		r = ccn_charbuf_append(cb, interest->buf + pi->offset[CCN_PI_B_Name],
				len);
		JUMP_IF_NEG_MEM(r, error);

		py_o = Name_obj_from_ccn(py_cname);
		Py_DECREF(py_cname);
		JUMP_IF_NULL(py_o, error);

		r = PyObject_SetAttrString(py_obj_Interest, "name", py_o);
		Py_DECREF(py_o);
		JUMP_IF_NEG(r, error);
	} else {
		PyErr_SetString(g_PyExc_CCNInterestError, "Got interest without a"
				" name!");
		goto error;
	}

	//        self.minSuffixComponents = None  # default 0
	len = pi->offset[CCN_PI_E_MinSuffixComponents] -
			pi->offset[CCN_PI_B_MinSuffixComponents];
	if (len > 0) {
		r = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_MinSuffixComponents,
				interest->buf, pi->offset[CCN_PI_B_MinSuffixComponents],
				pi->offset[CCN_PI_E_MinSuffixComponents]);
		if (r < 0) {
			PyErr_SetString(g_PyExc_CCNInterestError, "Invalid"
					" MinSuffixComponents value");
			goto error;
		}

		py_o = _pyccn_Int_FromLong(r);
		JUMP_IF_NULL(py_o, error);

		r = PyObject_SetAttrString(py_obj_Interest, "minSuffixComponents",
				py_o);
		Py_DECREF(py_o);
		JUMP_IF_NEG(r, error);
	}

	//        self.maxSuffixComponents = None  # default infinity
	len = pi->offset[CCN_PI_E_MaxSuffixComponents] -
			pi->offset[CCN_PI_B_MaxSuffixComponents];
	if (len > 0) {
		r = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_MaxSuffixComponents,
				interest->buf, pi->offset[CCN_PI_B_MaxSuffixComponents],
				pi->offset[CCN_PI_E_MaxSuffixComponents]);
		if (r < 0) {
			PyErr_SetString(g_PyExc_CCNInterestError, "Invalid"
					" MaxSuffixComponents value");
			goto error;
		}

		py_o = _pyccn_Int_FromLong(r);
		JUMP_IF_NULL(py_o, error);

		r = PyObject_SetAttrString(py_obj_Interest, "maxSuffixComponents",
				py_o);
		Py_DECREF(py_o);
		JUMP_IF_NEG(r, error);
	}

	//        self.publisherPublicKeyDigest = None   # SHA256 hash
	// TODO: what is CN_PI_B_PublisherID? -- looks like it is the data including
	//                                       the tags while PublisherIDKeyDigest
	//                                       is just the raw digest -- dk
	start = pi->offset[CCN_PI_B_PublisherID];
	end = pi->offset[CCN_PI_E_PublisherID];
	len = end - start;
	if (len > 0) {
		r = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest,
				interest->buf, start, end, &blob, &blob_size);
		if (r < 0) {
			PyErr_SetString(g_PyExc_CCNInterestError, "Invalid"
					" PublisherPublicKeyDigest value");
			goto error;
		}

		py_o = PyBytes_FromStringAndSize((const char*) blob, blob_size);
		JUMP_IF_NULL(py_o, error);

		r = PyObject_SetAttrString(py_obj_Interest, "publisherPublicKeyDigest",
				py_o);
		Py_DECREF(py_o);
		JUMP_IF_NEG(r, error);
	}

	//        self.exclude = None
	len = pi->offset[CCN_PI_E_Exclude] - pi->offset[CCN_PI_B_Exclude];
	if (len > 0) {
		PyObject *py_exclusion_filter;

		py_exclusion_filter = CCNObject_New_charbuf(EXCLUSION_FILTER, &cb);
		JUMP_IF_NULL(py_exclusion_filter, error);

		r = ccn_charbuf_append(cb, interest->buf + pi->offset[CCN_PI_B_Exclude],
				len);
		JUMP_IF_NEG_MEM(r, error);

		py_o = ExclusionFilter_obj_from_ccn(py_exclusion_filter);
		Py_DECREF(py_exclusion_filter);
		JUMP_IF_NULL(py_o, error);

		r = PyObject_SetAttrString(py_obj_Interest, "exclude", py_o);
		Py_DECREF(py_o);
		JUMP_IF_NEG(r, error);
	}

	//        self.childSelector = None
	len = pi->offset[CCN_PI_E_ChildSelector] -
			pi->offset[CCN_PI_B_ChildSelector];
	if (len > 0) {
		r = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_ChildSelector,
				interest->buf, pi->offset[CCN_PI_B_ChildSelector],
				pi->offset[CCN_PI_E_ChildSelector]);
		if (r < 0) {
			PyErr_SetString(g_PyExc_CCNInterestError, "Invalid"
					" ChildSelector value");
			goto error;
		}

		py_o = _pyccn_Int_FromLong(r);
		JUMP_IF_NULL(py_o, error);

		r = PyObject_SetAttrString(py_obj_Interest, "childSelector", py_o);
		Py_DECREF(py_o);
		JUMP_IF_NEG(r, error);
	}

	//        self.answerOriginKind = None
	len = pi->offset[CCN_PI_E_AnswerOriginKind] -
			pi->offset[CCN_PI_B_AnswerOriginKind];
	if (len > 0) {
		r = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_AnswerOriginKind,
				interest->buf, pi->offset[CCN_PI_B_AnswerOriginKind],
				pi->offset[CCN_PI_E_AnswerOriginKind]);
		if (r < 0) {
			PyErr_SetString(g_PyExc_CCNInterestError, "Invalid"
					" AnswerOriginKind value");
			goto error;
		}

		py_o = _pyccn_Int_FromLong(r);
		JUMP_IF_NULL(py_o, error);

		r = PyObject_SetAttrString(py_obj_Interest, "answerOriginKind", py_o);
		Py_DECREF(py_o);
		JUMP_IF_NEG(r, error);
	}

	//        self.scope  = None
	len = pi->offset[CCN_PI_E_Scope] - pi->offset[CCN_PI_B_Scope];
	if (len > 0) {
		r = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_Scope, interest->buf,
				pi->offset[CCN_PI_B_Scope], pi->offset[CCN_PI_E_Scope]);
		if (r < 0) {
			PyErr_SetString(g_PyExc_CCNInterestError, "Invalid"
					" Scope value");
			goto error;
		}

		py_o = _pyccn_Int_FromLong(r);
		JUMP_IF_NULL(py_o, error);

		r = PyObject_SetAttrString(py_obj_Interest, "scope", py_o);
		Py_DECREF(py_o);
		JUMP_IF_NEG(r, error);
	}

	//        self.interestLifetime = None
	len = pi->offset[CCN_PI_E_InterestLifetime] -
			pi->offset[CCN_PI_B_InterestLifetime];
	if (len > 0) {
		double lifetime;

		// From packet-ccn.c
		r = ccn_ref_tagged_BLOB(CCN_DTAG_InterestLifetime, interest->buf,
				pi->offset[CCN_PI_B_InterestLifetime],
				pi->offset[CCN_PI_E_InterestLifetime], &blob, &blob_size);
		if (r < 0) {
			PyErr_SetString(g_PyExc_CCNInterestError, "Invalid"
					" InterestLifetime value");
			goto error;
		}

		/* XXX: probably won't work with bigendian */
		lifetime = 0.0;
		for (size_t i = 0; i < blob_size; i++)
			lifetime = lifetime * 256.0 + (double) blob[i];
		lifetime /= 4096.0;

		py_o = PyFloat_FromDouble(lifetime);
		JUMP_IF_NULL(py_o, error);

		r = PyObject_SetAttrString(py_obj_Interest, "interestLifetime", py_o);
		Py_DECREF(py_o);
		JUMP_IF_NEG(r, error);
	}

	//        self.nonce = None
	len = pi->offset[CCN_PI_E_Nonce] - pi->offset[CCN_PI_B_Nonce];
	if (len > 0) {
		r = ccn_ref_tagged_BLOB(CCN_DTAG_Nonce, interest->buf,
				pi->offset[CCN_PI_B_Nonce], pi->offset[CCN_PI_E_Nonce], &blob,
				&blob_size);
		if (r < 0) {
			PyErr_SetString(g_PyExc_CCNInterestError, "Invalid"
					" Nonce value");
			goto error;
		}

		py_o = PyBytes_FromStringAndSize((const char *) blob, blob_size);
		JUMP_IF_NULL(py_o, error);

		r = PyObject_SetAttrString(py_obj_Interest, "nonce", py_o);
		Py_DECREF(py_o);
		JUMP_IF_NEG(r, error);
	}

	r = PyObject_SetAttrString(py_obj_Interest, "ccn_data_dirty", Py_False);
	JUMP_IF_NEG(r, error);

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

	return py_obj_Interest;

error:
	Py_DECREF(py_obj_Interest);

	return NULL;
}
예제 #12
0
static PyObject *
ExclusionFilter_names_to_ccn(PyObject *py_obj_Names)
{
	PyObject *py_iterator = NULL, *py_item = NULL;
	PyObject *py_exclude, *py_o;
	struct ccn_charbuf *exclude, *name;
	int r;

	//  Build exclusion list - This uses explicit exclusion rather than
	//                         Bloom filters as Bloom will be deprecated
	//  IMPORTANT:  Exclusion component list must be sorted following
	//              "Canonical CCNx ordering"
	//              http://www.ccnx.org/releases/latest/doc/technical/CanonicalOrder.html
	//              in which shortest components go first.
	// This sorting is expected to be handled on the Python side, not here.

	assert(py_obj_Names);

	py_exclude = CCNObject_New_charbuf(EXCLUSION_FILTER, &exclude);
	JUMP_IF_NULL(py_exclude, error);

	if (py_obj_Names == Py_None)
		return py_exclude;

	r = ccn_charbuf_append_tt(exclude, CCN_DTAG_Exclude, CCN_DTAG);
	JUMP_IF_NEG_MEM(r, error);

	// This code is similar to what's used in Name;
	// could probably be generalized.

	py_iterator = PyObject_GetIter(py_obj_Names);
	JUMP_IF_NULL(py_iterator, error);

	while ((py_item = PyIter_Next(py_iterator))) {
		int type;

		if (!PyObject_IsInstance(py_item, g_type_Name)) {
			PyErr_SetString(PyExc_ValueError, "Expected Name element");
			goto error;
		}

		py_o = PyObject_GetAttrString(py_item, "type");
		JUMP_IF_NULL(py_o, error);

		type = PyLong_AsLong(py_o);
		Py_DECREF(py_o);
		JUMP_IF_ERR(error);

		if (type == 0) {
			py_o = PyObject_GetAttrString(py_item, "ccn_data");
			JUMP_IF_NULL(py_o, error);

			if (!CCNObject_IsValid(NAME, py_o)) {
				Py_DECREF(py_o);
				PyErr_SetString(PyExc_TypeError, "Expected CCN Name");
				goto error;
			}

			name = CCNObject_Get(NAME, py_o);

			/* append without CCN name tag */
			assert(name->length >= 4);
			r = ccn_charbuf_append(exclude, name->buf + 1, name->length - 2);
			Py_DECREF(py_o);
			JUMP_IF_NEG_MEM(r, error);
		} else if (type == 1) {
			r = ccn_charbuf_append_tt(exclude, CCN_DTAG_Any, CCN_DTAG);
			JUMP_IF_NEG_MEM(r, error);

			r = ccn_charbuf_append_closer(exclude);
			JUMP_IF_NEG_MEM(r, error);
		} else {
			PyErr_SetString(PyExc_ValueError, "Unhandled Name type");
			goto error;
		}

		Py_CLEAR(py_item);
	}
	Py_CLEAR(py_iterator);

	r = ccn_charbuf_append_closer(exclude); /* </Exclude> */
	JUMP_IF_NEG_MEM(r, error);

	return py_exclude;

error:
	Py_XDECREF(py_item);
	Py_XDECREF(py_iterator);
	Py_XDECREF(py_exclude);
	return NULL;
}
예제 #13
0
static PyObject *
Interest_obj_to_ccn(PyObject *py_obj_Interest)
{
	struct ccn_charbuf *interest;
	PyObject *py_interest, *py_o;
	int r;

	py_interest = CCNObject_New_charbuf(INTEREST, &interest);
	if (!py_interest)
		return NULL;

	r = ccn_charbuf_append_tt(interest, CCN_DTAG_Interest, CCN_DTAG);
	JUMP_IF_NEG_MEM(r, error);

	/* Name */
	{
		struct ccn_charbuf *name;
		PyObject *py_name;

		r = is_attr_set(py_obj_Interest, "name", &py_o);
		JUMP_IF_NEG(r, error);

		if (r) {
			py_name = Name_obj_to_ccn(py_o);
			Py_DECREF(py_o);
			JUMP_IF_NULL(py_name, error);
			name = CCNObject_Get(NAME, py_name);

			r = ccn_charbuf_append_charbuf(interest, name);
			Py_DECREF(py_name);
			JUMP_IF_NEG_MEM(r, error);
		} else {
			// Even though Name is mandatory we still use this code to generate
			// templates, so it is ok if name is not given, the code below
			// creates an empty tag
			r = ccn_charbuf_append_tt(interest, CCN_DTAG_Name, CCN_DTAG);
			JUMP_IF_NEG(r, error);

			r = ccn_charbuf_append_closer(interest); /* </Name> */
			JUMP_IF_NEG(r, error);
		}
	}

	r = process_int_attribute(interest, CCN_DTAG_MinSuffixComponents,
			py_obj_Interest, "minSuffixComponents");
	JUMP_IF_NEG(r, error);

	r = process_int_attribute(interest, CCN_DTAG_MaxSuffixComponents,
			py_obj_Interest, "maxSuffixComponents");
	JUMP_IF_NEG(r, error);

	r = is_attr_set(py_obj_Interest, "publisherPublicKeyDigest", &py_o);
	JUMP_IF_NEG(r, error);
	if (r) {
		const char *blob;
		Py_ssize_t blobsize;

		blob = PyBytes_AsString(py_o);
		if (!blob) {
			Py_DECREF(py_o);
			goto error;
		}
		blobsize = PyBytes_GET_SIZE(py_o);

		r = ccnb_append_tagged_blob(interest, CCN_DTAG_PublisherPublicKeyDigest,
				blob, blobsize);
		Py_DECREF(py_o);
		JUMP_IF_NEG_MEM(r, error);
	}

	r = is_attr_set(py_obj_Interest, "exclude", &py_o);
	JUMP_IF_NEG(r, error);
	if (r) {
		PyObject *py_exclusions;
		struct ccn_charbuf *exclusion_filter;

		if (!PyObject_IsInstance(py_o, g_type_ExclusionFilter)) {
			Py_DECREF(py_o);
			PyErr_SetString(PyExc_TypeError, "Expected ExclusionFilter");
			goto error;
		}

		r = is_attr_set(py_o, "ccn_data", &py_exclusions);
		Py_DECREF(py_o);
		JUMP_IF_NEG(r, error);

		exclusion_filter = CCNObject_Get(EXCLUSION_FILTER, py_exclusions);
		r = ccn_charbuf_append_charbuf(interest, exclusion_filter);
		Py_DECREF(py_exclusions);
		JUMP_IF_NEG(r, error);
	}

	r = process_int_attribute(interest, CCN_DTAG_ChildSelector,
			py_obj_Interest, "childSelector");
	JUMP_IF_NEG(r, error);

	r = process_int_attribute(interest, CCN_DTAG_AnswerOriginKind,
			py_obj_Interest, "answerOriginKind");
	JUMP_IF_NEG(r, error);

	r = process_int_attribute(interest, CCN_DTAG_Scope, py_obj_Interest,
			"scope");
	JUMP_IF_NEG(r, error);

	r = is_attr_set(py_obj_Interest, "interestLifetime", &py_o);
	if (r) {
		unsigned char buf[3] = {0};
		double lifetime;
		unsigned long i_lifetime;

		if (!PyFloat_Check(py_o)) {
			Py_DECREF(py_o);
			PyErr_SetString(PyExc_TypeError, "expected float type in interest"
					" lifetime");
			goto error;
		}

		lifetime = PyFloat_AS_DOUBLE(py_o);
		Py_DECREF(py_o);

		i_lifetime = lifetime * 4096;

		/* XXX: probably won't work in bigendian */
		for (int i = sizeof(buf) - 1; i >= 0; i--, i_lifetime >>= 8)
			buf[i] = i_lifetime & 0xff;

		r = ccnb_append_tagged_blob(interest, CCN_DTAG_InterestLifetime,
				buf, sizeof(buf));
		JUMP_IF_NEG_MEM(r, error);
	}

	r = is_attr_set(py_obj_Interest, "nonce", &py_o);
	if (r) {
		char *s;
		Py_ssize_t len;

		r = PyBytes_AsStringAndSize(py_o, &s, &len);
		if (r < 0) {
			Py_DECREF(py_o);
			goto error;
		}

		r = ccnb_append_tagged_blob(interest, CCN_DTAG_Nonce, s, len);
		Py_DECREF(py_o);
		JUMP_IF_NEG_MEM(r, error);
	}

	r = ccn_charbuf_append_closer(interest); /* </Interest> */
	JUMP_IF_NEG_MEM(r, error);

	return py_interest;

error:
	Py_DECREF(py_interest);

	return NULL;
}
예제 #14
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;
}
예제 #15
0
PyObject *
_pyccn_cmd_SignedInfo_to_ccn(PyObject *UNUSED(self), PyObject *args,
		PyObject *kwds)
{
	static char *kwlist[] = {"pubkey_digest", "type", "timestamp",
		"freshness", "final_block_id", "key_locator", NULL};

	PyObject *py_pubkey_digest, *py_timestamp = Py_None,
			*py_final_block = Py_None, *py_key_locator = Py_None;
	struct ccn_charbuf *si;
	PyObject *py_si;
	int r;
	size_t publisher_key_id_size;
	const void *publisher_key_id;
	int type, freshness = -1;
	struct ccn_charbuf *timestamp = NULL, *finalblockid = NULL,
			*key_locator = NULL;

	if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oi|OiOO", kwlist,
			&py_pubkey_digest, &type, &py_timestamp, &freshness,
			&py_final_block, &py_key_locator))
		return NULL;

	if (!PyBytes_Check(py_pubkey_digest)) {
		PyErr_SetString(PyExc_TypeError, "Must pass a Bytes as pubkey_digest");
		return NULL;
	} else {
		publisher_key_id_size = PyBytes_GET_SIZE(py_pubkey_digest);
		publisher_key_id = PyBytes_AS_STRING(py_pubkey_digest);
	}

	if (py_timestamp != Py_None) {
		PyErr_SetString(PyExc_NotImplementedError, "Timestamp is not implemented yet");
		return NULL;
	} else
		timestamp = NULL;

	if (py_final_block != Py_None) {
		char *s;
		Py_ssize_t len;

		if (!PyBytes_Check(py_final_block)) {
			PyErr_SetString(PyExc_TypeError, "Must pass a bytes as final block");
			return NULL;
		}

		finalblockid = ccn_charbuf_create();
		JUMP_IF_NULL_MEM(finalblockid, error);

		s = PyBytes_AS_STRING(py_final_block);
		len = PyBytes_GET_SIZE(py_final_block);

		r = ccn_charbuf_append_tt(finalblockid, len, CCN_BLOB);
		JUMP_IF_NEG_MEM(r, error);

		r = ccn_charbuf_append(finalblockid, s, len);
		JUMP_IF_NEG_MEM(r, error);
	} else
		finalblockid = NULL;

	if (py_key_locator == Py_None)
		key_locator = NULL;
	else if (CCNObject_IsValid(KEY_LOCATOR, py_key_locator))
		key_locator = CCNObject_Get(KEY_LOCATOR, py_key_locator);
	else {
		PyErr_SetString(PyExc_TypeError, "key_locator needs to be a CCN KeyLocator object");
		return NULL;
	}

	py_si = CCNObject_New_charbuf(SIGNED_INFO, &si);
	JUMP_IF_NULL(py_si, error);

	r = ccn_signed_info_create(si, publisher_key_id, publisher_key_id_size,
			timestamp, type, freshness, finalblockid, key_locator);
	ccn_charbuf_destroy(&finalblockid);

	if (r < 0) {
		Py_DECREF(py_si);
		PyErr_SetString(g_PyExc_CCNError, "Error while creating SignedInfo");
		return NULL;
	}

	return py_si;

error:
	ccn_charbuf_destroy(&finalblockid);
	return NULL;
}
예제 #16
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;
}