static enum _ecore_status_t ecore_mfw_update_tlvs(struct ecore_hwfn *p_hwfn, u8 tlv_group, u8 *p_mfw_buf, u32 size) { union ecore_mfw_tlv_data *p_tlv_data; struct ecore_tlv_parsed_buf buffer; struct ecore_drv_tlv_hdr tlv; u32 offset; int len; u8 *p_tlv; p_tlv_data = OSAL_VZALLOC(p_hwfn->p_dev, sizeof(*p_tlv_data)); if (!p_tlv_data) return ECORE_NOMEM; if (OSAL_MFW_FILL_TLV_DATA(p_hwfn,tlv_group, p_tlv_data)) { OSAL_VFREE(p_hwfn->p_dev, p_tlv_data); return ECORE_INVAL; } OSAL_MEMSET(&tlv, 0, sizeof(tlv)); for (offset = 0; offset < size; offset += sizeof(tlv) + sizeof(u32) * tlv.tlv_length) { p_tlv = &p_mfw_buf[offset]; tlv.tlv_type = TLV_TYPE(p_tlv); tlv.tlv_length = TLV_LENGTH(p_tlv); tlv.tlv_flags = TLV_FLAGS(p_tlv); DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "Type %d length = %d flags = 0x%x\n", tlv.tlv_type, tlv.tlv_length, tlv.tlv_flags); if (tlv_group == ECORE_MFW_TLV_GENERIC) len = ecore_mfw_get_gen_tlv_value(&tlv, &p_tlv_data->generic, &buffer); else if (tlv_group == ECORE_MFW_TLV_ETH) len = ecore_mfw_get_eth_tlv_value(&tlv, &p_tlv_data->eth, &buffer); else if (tlv_group == ECORE_MFW_TLV_FCOE) len = ecore_mfw_get_fcoe_tlv_value(&tlv, &p_tlv_data->fcoe, &buffer); else len = ecore_mfw_get_iscsi_tlv_value(&tlv, &p_tlv_data->iscsi, &buffer); if (len > 0) { OSAL_WARN(len > 4 * tlv.tlv_length, "Incorrect MFW TLV length %d, it shouldn't be greater than %d\n", len, 4 * tlv.tlv_length); len = OSAL_MIN_T(int, len, 4 * tlv.tlv_length); tlv.tlv_flags |= ECORE_DRV_TLV_FLAGS_CHANGED; TLV_FLAGS(p_tlv) = tlv.tlv_flags; OSAL_MEMCPY(p_mfw_buf + offset + sizeof(tlv), buffer.p_val, len); } }
int tipc_cfg_append_tlv(struct sk_buff *buf, int tlv_type, void *tlv_data, int tlv_data_size) { struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(buf); int new_tlv_space = TLV_SPACE(tlv_data_size); if (skb_tailroom(buf) < new_tlv_space) return 0; skb_put(buf, new_tlv_space); tlv->tlv_type = htons(tlv_type); tlv->tlv_len = htons(TLV_LENGTH(tlv_data_size)); if (tlv_data_size && tlv_data) memcpy(TLV_DATA(tlv), tlv_data, tlv_data_size); return 1; }
static int tipc_add_tlv(struct sk_buff *skb, u16 type, void *data, u16 len) { struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(skb); if (tipc_skb_tailroom(skb) < TLV_SPACE(len)) return -EMSGSIZE; skb_put(skb, TLV_SPACE(len)); tlv->tlv_type = htons(type); tlv->tlv_len = htons(TLV_LENGTH(len)); if (len && data) memcpy(TLV_DATA(tlv), data, len); return 0; }
gpg_error_t _ksba_keyinfo_to_sexp (const unsigned char *der, size_t derlen, ksba_sexp_t *r_string) { gpg_error_t err; int c; size_t nread, off, len, parm_off, parm_len; int parm_type; char *parm_oid = NULL; int algoidx; int is_bitstr; const unsigned char *parmder = NULL; size_t parmderlen = 0; const unsigned char *ctrl; const char *elem; struct stringbuf sb; *r_string = NULL; /* check the outer sequence */ if (!derlen) return gpg_error (GPG_ERR_INV_KEYINFO); c = *der++; derlen--; if ( c != 0x30 ) return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not a SEQUENCE */ TLV_LENGTH(der); /* and now the inner part */ err = get_algorithm (1, der, derlen, &nread, &off, &len, &is_bitstr, &parm_off, &parm_len, &parm_type); if (err) return err; /* look into our table of supported algorithms */ for (algoidx=0; pk_algo_table[algoidx].oid; algoidx++) { if ( len == pk_algo_table[algoidx].oidlen && !memcmp (der+off, pk_algo_table[algoidx].oid, len)) break; } if (!pk_algo_table[algoidx].oid) return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM); if (!pk_algo_table[algoidx].supported) return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); if (parm_off && parm_len && parm_type == TYPE_OBJECT_ID) parm_oid = ksba_oid_to_str (der+parm_off, parm_len); else if (parm_off && parm_len) { parmder = der + parm_off; parmderlen = parm_len; } der += nread; derlen -= nread; if (is_bitstr) { /* Funny: X.509 defines the signature value as a bit string but CMS as an octet string - for ease of implementation we always allow both */ if (!derlen) { xfree (parm_oid); return gpg_error (GPG_ERR_INV_KEYINFO); } c = *der++; derlen--; if (c) fprintf (stderr, "warning: number of unused bits is not zero\n"); } /* fixme: we should calculate the initial length form the size of the sequence, so that we don't need a realloc later */ init_stringbuf (&sb, 100); put_stringbuf (&sb, "(10:public-key("); /* fixme: we can also use the oidstring here and prefix it with "oid." - this way we can pass more information into Libgcrypt or whatever library is used */ put_stringbuf_sexp (&sb, pk_algo_table[algoidx].algo_string); /* Insert the curve name for ECC. */ if (pk_algo_table[algoidx].pkalgo == PKALGO_ECC && parm_oid) { put_stringbuf (&sb, "("); put_stringbuf_sexp (&sb, "curve"); put_stringbuf_sexp (&sb, parm_oid); put_stringbuf (&sb, ")"); } /* If parameters are given and we have a description for them, parse them. */ if (parmder && parmderlen && pk_algo_table[algoidx].parmelem_string && pk_algo_table[algoidx].parmctrl_string) { elem = pk_algo_table[algoidx].parmelem_string; ctrl = pk_algo_table[algoidx].parmctrl_string; for (; *elem; ctrl++, elem++) { int is_int; if ( (*ctrl & 0x80) && !elem[1] ) { /* Hack to allow reading a raw value. */ is_int = 1; len = parmderlen; } else { if (!parmderlen) { xfree (parm_oid); return gpg_error (GPG_ERR_INV_KEYINFO); } c = *parmder++; parmderlen--; if ( c != *ctrl ) { xfree (parm_oid); return gpg_error (GPG_ERR_UNEXPECTED_TAG); } is_int = c == 0x02; TLV_LENGTH (parmder); } if (is_int && *elem != '-') /* Take this integer. */ { char tmp[2]; put_stringbuf (&sb, "("); tmp[0] = *elem; tmp[1] = 0; put_stringbuf_sexp (&sb, tmp); put_stringbuf_mem_sexp (&sb, parmder, len); parmder += len; parmderlen -= len; put_stringbuf (&sb, ")"); } } } /* FIXME: We don't release the stringbuf in case of error better let the macro jump to a label */ elem = pk_algo_table[algoidx].elem_string; ctrl = pk_algo_table[algoidx].ctrl_string; for (; *elem; ctrl++, elem++) { int is_int; if ( (*ctrl & 0x80) && !elem[1] ) { /* Hack to allow reading a raw value. */ is_int = 1; len = derlen; } else { if (!derlen) { xfree (parm_oid); return gpg_error (GPG_ERR_INV_KEYINFO); } c = *der++; derlen--; if ( c != *ctrl ) { xfree (parm_oid); return gpg_error (GPG_ERR_UNEXPECTED_TAG); } is_int = c == 0x02; TLV_LENGTH (der); } if (is_int && *elem != '-') /* Take this integer. */ { char tmp[2]; put_stringbuf (&sb, "("); tmp[0] = *elem; tmp[1] = 0; put_stringbuf_sexp (&sb, tmp); put_stringbuf_mem_sexp (&sb, der, len); der += len; derlen -= len; put_stringbuf (&sb, ")"); } } put_stringbuf (&sb, "))"); xfree (parm_oid); *r_string = get_stringbuf (&sb); if (!*r_string) return gpg_error (GPG_ERR_ENOMEM); return 0; }
/* Return the OFF and the LEN of algorithm within DER. Do some checks and return the number of bytes read in r_nread, adding this to der does point into the BIT STRING. mode 0: just get the algorithm identifier. FIXME: should be able to handle BER Encoding. mode 1: as described. */ static gpg_error_t get_algorithm (int mode, const unsigned char *der, size_t derlen, size_t *r_nread, size_t *r_pos, size_t *r_len, int *r_bitstr, size_t *r_parm_pos, size_t *r_parm_len, int *r_parm_type) { int c; const unsigned char *start = der; const unsigned char *startseq; unsigned long seqlen, len; *r_bitstr = 0; if (r_parm_pos) *r_parm_pos = 0; if (r_parm_len) *r_parm_len = 0; if (r_parm_type) *r_parm_type = 0; /* get the inner sequence */ if (!derlen) return gpg_error (GPG_ERR_INV_KEYINFO); c = *der++; derlen--; if ( c != 0x30 ) return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not a SEQUENCE */ TLV_LENGTH(der); seqlen = len; startseq = der; /* get the object identifier */ if (!derlen) return gpg_error (GPG_ERR_INV_KEYINFO); c = *der++; derlen--; if ( c != 0x06 ) return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not an OBJECT IDENTIFIER */ TLV_LENGTH(der); /* der does now point to an oid of length LEN */ *r_pos = der - start; *r_len = len; /* { */ /* char *p = ksba_oid_to_str (der, len); */ /* printf ("algorithm: %s\n", p); */ /* xfree (p); */ /* } */ der += len; derlen -= len; seqlen -= der - startseq;; /* Parse the parameter. */ if (seqlen) { const unsigned char *startparm = der; if (!derlen) return gpg_error (GPG_ERR_INV_KEYINFO); c = *der++; derlen--; if ( c == 0x05 ) { /*printf ("parameter: NULL \n"); the usual case */ if (!derlen) return gpg_error (GPG_ERR_INV_KEYINFO); c = *der++; derlen--; if (c) return gpg_error (GPG_ERR_BAD_BER); /* NULL must have a length of 0 */ seqlen -= 2; } else if (r_parm_pos && r_parm_len && c == 0x04) { /* This is an octet string parameter and we need it. */ if (r_parm_type) *r_parm_type = TYPE_OCTET_STRING; TLV_LENGTH(der); *r_parm_pos = der - start; *r_parm_len = len; seqlen -= der - startparm; der += len; derlen -= len; seqlen -= len; } else if (r_parm_pos && r_parm_len && c == 0x06) { /* This is an object identifier. */ if (r_parm_type) *r_parm_type = TYPE_OBJECT_ID; TLV_LENGTH(der); *r_parm_pos = der - start; *r_parm_len = len; seqlen -= der - startparm; der += len; derlen -= len; seqlen -= len; } else if (r_parm_pos && r_parm_len && c == 0x30) { /* This is a sequence. */ if (r_parm_type) *r_parm_type = TYPE_SEQUENCE; TLV_LENGTH(der); *r_parm_pos = startparm - start; *r_parm_len = len + (der - startparm); seqlen -= der - startparm; der += len; derlen -= len; seqlen -= len; } else { /* printf ("parameter: with tag %02x - ignored\n", c); */ TLV_LENGTH(der); seqlen -= der - startparm; /* skip the value */ der += len; derlen -= len; seqlen -= len; } } if (seqlen) return gpg_error (GPG_ERR_INV_KEYINFO); if (mode) { /* move forward to the BIT_STR */ if (!derlen) return gpg_error (GPG_ERR_INV_KEYINFO); c = *der++; derlen--; if (c == 0x03) *r_bitstr = 1; /* BIT STRING */ else if (c == 0x04) ; /* OCTECT STRING */ else return gpg_error (GPG_ERR_UNEXPECTED_TAG); /* not a BIT STRING */ TLV_LENGTH(der); } *r_nread = der - start; return 0; }
/* Mode 0: work as described under _ksba_sigval_to_sexp mode 1: work as described under _ksba_encval_to_sexp */ static gpg_error_t cryptval_to_sexp (int mode, const unsigned char *der, size_t derlen, ksba_sexp_t *r_string) { gpg_error_t err; const struct algo_table_s *algo_table; int c; size_t nread, off, len; int algoidx; int is_bitstr; const unsigned char *ctrl; const char *elem; struct stringbuf sb; /* FIXME: The entire function is very similar to keyinfo_to_sexp */ *r_string = NULL; if (!mode) algo_table = sig_algo_table; else algo_table = enc_algo_table; err = get_algorithm (1, der, derlen, &nread, &off, &len, &is_bitstr, NULL, NULL, NULL); if (err) return err; /* look into our table of supported algorithms */ for (algoidx=0; algo_table[algoidx].oid; algoidx++) { if ( len == algo_table[algoidx].oidlen && !memcmp (der+off, algo_table[algoidx].oid, len)) break; } if (!algo_table[algoidx].oid) return gpg_error (GPG_ERR_UNKNOWN_ALGORITHM); if (!algo_table[algoidx].supported) return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); der += nread; derlen -= nread; if (is_bitstr) { /* Funny: X.509 defines the signature value as a bit string but CMS as an octet string - for ease of implementation we always allow both */ if (!derlen) return gpg_error (GPG_ERR_INV_KEYINFO); c = *der++; derlen--; if (c) fprintf (stderr, "warning: number of unused bits is not zero\n"); } /* fixme: we should calculate the initial length form the size of the sequence, so that we don't neen a realloc later */ init_stringbuf (&sb, 100); put_stringbuf (&sb, mode? "(7:enc-val(":"(7:sig-val("); put_stringbuf_sexp (&sb, algo_table[algoidx].algo_string); /* FIXME: We don't release the stringbuf in case of error better let the macro jump to a label */ elem = algo_table[algoidx].elem_string; ctrl = algo_table[algoidx].ctrl_string; for (; *elem; ctrl++, elem++) { int is_int; if ( (*ctrl & 0x80) && !elem[1] ) { /* Hack to allow a raw value */ is_int = 1; len = derlen; } else { if (!derlen) return gpg_error (GPG_ERR_INV_KEYINFO); c = *der++; derlen--; if ( c != *ctrl ) return gpg_error (GPG_ERR_UNEXPECTED_TAG); is_int = c == 0x02; TLV_LENGTH (der); } if (is_int && *elem != '-') { /* take this integer */ char tmp[2]; put_stringbuf (&sb, "("); tmp[0] = *elem; tmp[1] = 0; put_stringbuf_sexp (&sb, tmp); put_stringbuf_mem_sexp (&sb, der, len); der += len; derlen -= len; put_stringbuf (&sb, ")"); } } put_stringbuf (&sb, ")"); if (!mode && algo_table[algoidx].digest_string) { /* Insert the hash algorithm if included in the OID. */ put_stringbuf (&sb, "(4:hash"); put_stringbuf_sexp (&sb, algo_table[algoidx].digest_string); put_stringbuf (&sb, ")"); } put_stringbuf (&sb, ")"); *r_string = get_stringbuf (&sb); if (!*r_string) return gpg_error (GPG_ERR_ENOMEM); return 0; }