fn refresh_token()

in src/vtok_srv/src/worker.rs [168:224]


    fn refresh_token(label: String, pin: String, envelope_key: schema::EnvelopeKey) -> ApiResponse {
        let mut config = config::Config::load_rw().map_err(|_| ApiError::InternalError)?;
        let slot = config
            .slots_mut()
            .iter_mut()
            .find(|s| match s {
                None => false,
                Some(tok) => tok.label == label,
            })
            .ok_or(ApiError::TokenNotFound)?;

        // It's safe to unwrap here, since the above find() ensures slot != None
        let mut token = slot.as_mut().unwrap();
        if token.pin != pin {
            return Err(ApiError::AccessDenied);
        }

        // Since all the keys in one token are encrypted via the same envelope, we only need to
        // successfully decrypt one key, in order to achieve attestation.
        token
            .private_keys
            .iter()
            .next()
            .ok_or(ApiError::EmptyToken)
            .and_then(|key| {
                match envelope_key {
                    schema::EnvelopeKey::Kms {
                        ref region,
                        ref access_key_id,
                        ref secret_access_key,
                        ref session_token,
                    } => {
                        aws_ne::kms_decrypt(
                            region.as_bytes(),
                            access_key_id.as_bytes(),
                            secret_access_key.as_bytes(),
                            session_token.as_bytes(),
                            &base64::decode(key.encrypted_pem_b64.as_str())
                                .map_err(|_| ApiError::TokenKeyDecodingFailed)?,
                        )
                        .map_err(|_| ApiError::KmsDecryptFailed)
                        .and_then(|v| {
                            String::from_utf8(v).map_err(|_| ApiError::TokenRefreshFailed)
                        })
                        .ok()
                        .filter(|pem| pem == &key.pem)
                        .ok_or(ApiError::TokenRefreshFailed)?;
                    }
                };
                Ok(())
            })?;
        token.expiry_ts = util::time::monotonic_secs() + defs::TOKEN_EXPIRY_SECS;

        config.save().map_err(|_| ApiError::InternalError)?;

        Ok(ApiOk::None)
    }