int yp_scheme_check_parser( yp_check_ctx_t *ctx, const yp_parser_t *parser) { if (ctx == NULL || parser == NULL) { return KNOT_EINVAL; } int ret; switch (parser->event) { case YP_EKEY0: reset_ctx(ctx, 0); ret = check_item(parser->key, parser->key_len, parser->data, parser->data_len, ctx, false); break; case YP_EKEY1: reset_ctx(ctx, 1); ret = check_item(parser->key, parser->key_len, parser->data, parser->data_len, ctx, false); if (ret != KNOT_EOK) { break; } // Check for KEY1 event with id item. if (ctx->current != 1) { return KNOT_YP_ENOTSUP_ID; } break; case YP_EID: reset_ctx(ctx, 1); ret = check_item(parser->key, parser->key_len, parser->data, parser->data_len, ctx, false); if (ret != KNOT_EOK) { break; } // Check for ID event with nonid item. if (ctx->current != 0) { return KNOT_YP_EINVAL_ID; } break; default: ret = KNOT_EPARSEFAIL; break; } return ret; }
// Party B's step 2 // 4) Verify msg3: verify_pubA(D_k1(msg3)) && open(D_k1(msg3)) == (pubB_e, pubA_e) // Set the key material: key_material = k2 int finish_sts( const uint8_t msg3[MSG_3_LEN] // Party 'B' , gec_sts_ctx_t *ctx , uint8_t key_material[KEY_MATERIAL_LEN]) { int ret=-1; if(MESSAGE_2_DONE == ctx->protocol_stage) { if(verify(ctx, msg3) != 0) { ret = -1; } else { memcpy(key_material, ctx->client_key_material, KEY_MATERIAL_LEN); reset_ctx(ctx); ret = 0; } } return ret; }
// Party A's step 2 // 3) Compute the shared secret: kdf( ecdh(pubB_e, privA_e) ) // Verify msg2: verify_pubB(D_k1(msg2)) && open(D_k1(msg2)) == (pubA_e, pubB_e) // Construct the response: msg3 = E_k1( sign_privA(pubB_e, pubA_e) ) // Set the key material: key_material = some part of kdf int response_ack_sts( const uint8_t msg2[MSG_2_LEN] , uint8_t msg3[MSG_3_LEN] , gec_sts_ctx_t *ctx , uint8_t key_material[KEY_MATERIAL_LEN]) // Party 'A' { uint8_t z[GEC_SECRET_BYTES_LEN]; int sig_result; int ret = -1; if(MESSAGE_1_DONE == ctx->protocol_stage) { // Derive shared secret KDF( ECDH(Priv_B,PubA_E) ) memcpy(ctx->theirPublicKey_ephemeral, msg2, EPHEMERAL_PUBLICKEY_LEN); gec_ecdh(z, ctx->theirPublicKey_ephemeral, ctx->myPrivateKey_ephemeral); derive_key_materials(ctx, z); // verify msg2 sig_result = verify(ctx, msg2 + EPHEMERAL_PUBLICKEY_LEN); if(sig_result != 0) { ret = -1; } else { // Construct response [ E_k2 ( Sign_PubA ( PubA_E | PubB_E ) | PubA_E | PubB_E ) ] uint8_t unsigned_data[EPHEMERAL_PUBLICKEY_LEN * 2]; uint8_t concatKeysSig[2*EPHEMERAL_PUBLICKEY_LEN + GEC_SIG_LEN]; uint8_t sig[GEC_SIG_LEN]; memcpy(unsigned_data, ctx->myPublicKey_ephemeral, EPHEMERAL_PUBLICKEY_LEN); memcpy(unsigned_data + EPHEMERAL_PUBLICKEY_LEN, ctx->theirPublicKey_ephemeral, EPHEMERAL_PUBLICKEY_LEN); gec_sign(&ctx->myPrivateKey, unsigned_data, sizeof(unsigned_data), sig); gec_encrypt_conf(&ctx->myKCK, sig, msg3, GEC_SIG_LEN); memcpy(key_material, ctx->client_key_material, KEY_MATERIAL_LEN); reset_ctx(ctx); ret = 0; } } return ret; }
// Reset the context and set a new partner public key. // // Context is useful only when given the public keys for the ONE anticipated communication partner. void reset_partner(gec_sts_ctx_t *ctx, const struct gec_pubkey *theirPublicKey) { memcpy(&ctx->theirPublicKey, theirPublicKey, sizeof(struct gec_pubkey)); reset_ctx(ctx); }
int yp_scheme_check_str( yp_check_ctx_t *ctx, const char *key0, const char *key1, const char *id, const char *data) { if (ctx == NULL) { return KNOT_EINVAL; } size_t key0_len = (key0 != NULL) ? strlen(key0) : 0; size_t key1_len = (key1 != NULL) ? strlen(key1) : 0; size_t id_len = (id != NULL) ? strlen(id) : 0; size_t data_len = (data != NULL) ? strlen(data) : 0; // Key0 must always be non-empty. if (key0_len == 0) { return KNOT_YP_EINVAL_ITEM; } // Process key0. reset_ctx(ctx, 0); if (key1_len == 0) { int ret = check_item(key0, key0_len, data, data_len, ctx, false); if (ret != KNOT_EOK) { return ret; } } else { int ret = check_item(key0, key0_len, NULL, 0, ctx, false); if (ret != KNOT_EOK) { return ret; } } // Process id. if (id_len != 0) { if (ctx->nodes[0].item->type != YP_TGRP || ctx->nodes[0].item->var.g.id == NULL) { return KNOT_YP_ENOTSUP_ID; } const yp_name_t *name = ctx->nodes[0].item->var.g.id->name; reset_ctx(ctx, 1); int ret = check_item(name + 1, name[0], id, id_len, ctx, true); if (ret != KNOT_EOK) { return ret; } // Check for non-id item (should not happen). assert(ctx->current == 0); // Check for group id with data. if (key1_len == 0 && data != NULL) { return KNOT_YP_ENOTSUP_DATA; } } // Process key1. if (key1_len != 0) { reset_ctx(ctx, 1); int ret = check_item(key1, key1_len, data, data_len, ctx, true); if (ret != KNOT_EOK) { return ret; } // Check for id in key1 with extra data. if (ctx->current != 1 && id_len != 0 && data != NULL) { return KNOT_YP_ENOTSUP_DATA; } } return KNOT_EOK; }
ARMSIM_STATUS as_reset_cpu(ARMSIM_CTX *ctx) { reset_ctx(ctx); return AS_OK; }