/* =item C<static int get_signature_length(expression * const e)> Calculate the length of the signature for one operand; an operand is separated from the instruction name or another operand through '_', which must also be counted. set $I0, 42 --> set_i_ic therefore, for $I0 (a target), return 1 for the type, 1 for the '_', and whatever is needed for a key, if any, as in this example: set $P0[1] = "hi" --> set_p_kic_sc $P0 is a target, resulting in "_p", the key [1] is a key ('k') of type int ('i'), and it's a constant ('c'). Add 1 for the '_'. =cut */ PARROT_WARN_UNUSED_RESULT static int get_signature_length(NOTNULL(expression * const e)) { switch (e->type) { case EXPR_TARGET: return 2 + ((e->expr.t->key != NULL) /* if there's a key on this target ... */ /* ... get its length. */ ? get_signature_length(e->expr.t->key->head->expr) + 1 : 0); case EXPR_CONSTANT: return 3; /* for _, 'k', 'c' */ case EXPR_IDENT: return 3; /* 1 for '_', 1 for 'i', 1 for 'c' */ case EXPR_KEY: { /* for '_', 'k' */ int n; /* if the key is an integer constant, then signature becomes '_kic', otherwise _kc. */ if (e->expr.k->head->expr->type == EXPR_CONSTANT && e->expr.k->head->expr->expr.c->type == INT_VAL) n = 3; else n = 2; return n + get_signature_length(e->expr.k->head->expr); } default: fprintf(stderr, "wrong expression typein get_signature_length()\n"); break; } return 0; }
static int16_t u2f_register(struct u2f_register_request * req) { uint8_t i[] = {0x0,U2F_EC_FMT_UNCOMPRESSED}; uint8_t key_handle[U2F_KEY_HANDLE_SIZE]; uint8_t pubkey[64]; const uint16_t attest_size = u2f_attestation_cert_size(); if (u2f_get_user_feedback()) { return U2F_SW_CONDITIONS_NOT_SATISFIED; } if ( u2f_new_keypair(key_handle, pubkey) == -1) { return U2F_SW_CONDITIONS_NOT_SATISFIED; } u2f_sha256_start(); u2f_sha256_update(i,1); u2f_sha256_update(req->app,32); u2f_sha256_update(req->chal,32); u2f_sha256_update(key_handle,U2F_KEY_HANDLE_SIZE); u2f_sha256_update(i+1,1); u2f_sha256_update(pubkey,64); u2f_sha256_finish(); if (u2f_ecdsa_sign((uint8_t*)req, U2F_ATTESTATION_HANDLE) == -1) { return U2F_SW_WRONG_DATA; } u2f_hid_set_len(69 + get_signature_length((uint8_t*)req) + U2F_KEY_HANDLE_SIZE + u2f_attestation_cert_size()); i[0] = 0x5; u2f_response_writeback(i,2); u2f_response_writeback(pubkey,64); i[0] = U2F_KEY_HANDLE_SIZE; u2f_response_writeback(i,1); u2f_response_writeback(key_handle,U2F_KEY_HANDLE_SIZE); u2f_response_writeback_progmem(u2f_get_attestation_cert(),u2f_attestation_cert_size()); dump_signature_der((uint8_t*)req); return U2F_SW_NO_ERROR; }
/* =item C<static char * get_signatured_opname(instruction * const instr)> Returns the full opname of the instruction C<name>; the signature of the opname is based on the operands, some examples are shown below: set I0, 10 --> set_i_ic print "hi" --> print_sc set P0[1], 3.14 --> set_p_kic_nc For each operand, an underscore is added; then for the types int, num, string or pmc, an 'i', 'n', 's' or 'p' is added respectively. If the operand is a constant, a 'c' suffic is added. If the operand is a key of something, a 'k' prefix is added. =cut */ PARROT_WARN_UNUSED_RESULT PARROT_CANNOT_RETURN_NULL static char * get_signatured_opname(NOTNULL(lexer_state * const lexer), NOTNULL(instruction * const instr)) { size_t fullname_length; char *fullname; char *instr_writer; expression *iter = instr->operands; unsigned num_operands = 0; /* get length of short opname (and add 1 for the NULL character) */ fullname_length = strlen(instr->opname) + 1; /* for each operand, calculate the length of the signature (for that op.) * and add it to the full length. */ if (iter) { iter = iter->next; do { int keylength = get_signature_length(iter); fullname_length += keylength; iter = iter->next; ++num_operands; } while (iter != instr->operands->next); } /* now we know how long the fullname will be, allocate enough memory. */ fullname = (char *)pir_mem_allocate_zeroed(lexer, fullname_length * sizeof (char)); /* copy the short name into fullname buffer, and set instr_writer to * the character after that. */ strcpy(fullname, instr->opname); instr_writer = fullname + strlen(instr->opname); /* now iterate again over all operands, and codify them into the fullname. * As we counted the number of operands, this loop can be written a bit simpler. */ iter = instr->operands; while (num_operands-- > 0) { iter = iter->next; *instr_writer++ = '_'; /* separate each operand code by a '_' */ instr_writer = write_signature(iter, instr_writer); } return fullname; }
static int16_t u2f_authenticate(struct u2f_authenticate_request * req, uint8_t control) { uint8_t up = 1; uint32_t count; if (u2f_load_key(req->kh) != 0) { u2f_hid_set_len(2); return U2F_SW_WRONG_DATA; } else if (control == U2F_AUTHENTICATE_CHECK) { u2f_hid_set_len(2); return U2F_SW_CONDITIONS_NOT_SATISFIED; } if (u2f_get_user_feedback()) { u2f_hid_set_len(2); return U2F_SW_CONDITIONS_NOT_SATISFIED; } count = u2f_count(); u2f_sha256_start(); u2f_sha256_update(req->app,32); u2f_sha256_update(&up,1); u2f_sha256_update((uint8_t *)&count,4); u2f_sha256_update(req->chal,32); u2f_sha256_finish(); if (u2f_ecdsa_sign((uint8_t*)req, req->kh) == -1) { return U2F_SW_WRONG_DATA; } u2f_hid_set_len(7 + get_signature_length((uint8_t*)req)); u2f_response_writeback(&up,1); u2f_response_writeback((uint8_t *)&count,4); dump_signature_der((uint8_t*)req); return U2F_SW_NO_ERROR; }