Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit df66b729 authored by Yan Yan's avatar Yan Yan Committed by Automerger Merge Worker
Browse files

Merge changes I65dbc509,I1e338d9c,Ib4a0ed69,Iac7077b4,I9c53d425, ... am: 067b3dff

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1603710

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I53ca8ed01491465bfbfcb9df42ddf6218cc1a326
parents e37cfaa9 067b3dff
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.vcn.persistablebundleutils;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Objects;

/**
 * CertUtils provides utility methods for constructing Certificate.
 *
 * @hide
 */
public class CertUtils {
    private static final String CERT_TYPE_X509 = "X.509";

    /** Decodes an ASN.1 DER encoded Certificate */
    public static X509Certificate certificateFromByteArray(byte[] derEncoded) {
        Objects.requireNonNull(derEncoded, "derEncoded is null");

        try {
            CertificateFactory certFactory = CertificateFactory.getInstance(CERT_TYPE_X509);
            InputStream in = new ByteArrayInputStream(derEncoded);
            return (X509Certificate) certFactory.generateCertificate(in);
        } catch (CertificateException e) {
            throw new IllegalArgumentException("Fail to decode certificate", e);
        }
    }
}
+73 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.vcn.persistablebundleutils;

import static com.android.internal.annotations.VisibleForTesting.Visibility;

import android.annotation.NonNull;
import android.net.ipsec.ike.ChildSaProposal;
import android.os.PersistableBundle;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.vcn.util.PersistableBundleUtils;

import java.util.List;
import java.util.Objects;

/**
 * Provides utility methods to convert ChildSaProposal to/from PersistableBundle.
 *
 * @hide
 */
@VisibleForTesting(visibility = Visibility.PRIVATE)
public final class ChildSaProposalUtils extends SaProposalUtilsBase {
    /** Serializes a ChildSaProposal to a PersistableBundle. */
    @NonNull
    public static PersistableBundle toPersistableBundle(ChildSaProposal proposal) {
        return SaProposalUtilsBase.toPersistableBundle(proposal);
    }

    /** Constructs a ChildSaProposal by deserializing a PersistableBundle. */
    @NonNull
    public static ChildSaProposal fromPersistableBundle(@NonNull PersistableBundle in) {
        Objects.requireNonNull(in, "PersistableBundle was null");

        final ChildSaProposal.Builder builder = new ChildSaProposal.Builder();

        final PersistableBundle encryptionBundle = in.getPersistableBundle(ENCRYPT_ALGO_KEY);
        Objects.requireNonNull(encryptionBundle, "Encryption algo bundle was null");
        final List<EncryptionAlgoKeyLenPair> encryptList =
                PersistableBundleUtils.toList(encryptionBundle, EncryptionAlgoKeyLenPair::new);
        for (EncryptionAlgoKeyLenPair t : encryptList) {
            builder.addEncryptionAlgorithm(t.encryptionAlgo, t.keyLen);
        }

        final int[] integrityAlgoIdArray = in.getIntArray(INTEGRITY_ALGO_KEY);
        Objects.requireNonNull(integrityAlgoIdArray, "Integrity algo array was null");
        for (int algo : integrityAlgoIdArray) {
            builder.addIntegrityAlgorithm(algo);
        }

        final int[] dhGroupArray = in.getIntArray(DH_GROUP_KEY);
        Objects.requireNonNull(dhGroupArray, "DH Group array was null");
        for (int dh : dhGroupArray) {
            builder.addDhGroup(dh);
        }

        return builder.build();
    }
}
+276 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.vcn.persistablebundleutils;


import static com.android.internal.annotations.VisibleForTesting.Visibility;

import android.annotation.NonNull;
import android.net.eap.EapSessionConfig;
import android.net.eap.EapSessionConfig.EapAkaConfig;
import android.net.eap.EapSessionConfig.EapAkaPrimeConfig;
import android.net.eap.EapSessionConfig.EapMethodConfig;
import android.net.eap.EapSessionConfig.EapMsChapV2Config;
import android.net.eap.EapSessionConfig.EapSimConfig;
import android.net.eap.EapSessionConfig.EapTtlsConfig;
import android.net.eap.EapSessionConfig.EapUiccConfig;
import android.os.PersistableBundle;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.vcn.util.PersistableBundleUtils;

import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.Objects;

/**
 * Provides utility methods to convert EapSessionConfig to/from PersistableBundle.
 *
 * @hide
 */
@VisibleForTesting(visibility = Visibility.PRIVATE)
public final class EapSessionConfigUtils {
    private static final String EAP_ID_KEY = "EAP_ID_KEY";
    private static final String EAP_SIM_CONFIG_KEY = "EAP_SIM_CONFIG_KEY";
    private static final String EAP_TTLS_CONFIG_KEY = "EAP_TTLS_CONFIG_KEY";
    private static final String EAP_AKA_CONFIG_KEY = "EAP_AKA_CONFIG_KEY";
    private static final String EAP_MSCHAP_V2_CONFIG_KEY = "EAP_MSCHAP_V2_CONFIG_KEY";
    private static final String EAP_AKA_PRIME_CONFIG_KEY = "EAP_AKA_PRIME_CONFIG_KEY";

    /** Serializes an EapSessionConfig to a PersistableBundle. */
    @NonNull
    public static PersistableBundle toPersistableBundle(@NonNull EapSessionConfig config) {
        final PersistableBundle result = new PersistableBundle();

        result.putPersistableBundle(
                EAP_ID_KEY, PersistableBundleUtils.fromByteArray(config.getEapIdentity()));

        if (config.getEapSimConfig() != null) {
            result.putPersistableBundle(
                    EAP_SIM_CONFIG_KEY,
                    EapSimConfigUtils.toPersistableBundle(config.getEapSimConfig()));
        }

        if (config.getEapTtlsConfig() != null) {
            result.putPersistableBundle(
                    EAP_TTLS_CONFIG_KEY,
                    EapTtlsConfigUtils.toPersistableBundle(config.getEapTtlsConfig()));
        }

        if (config.getEapAkaConfig() != null) {
            result.putPersistableBundle(
                    EAP_AKA_CONFIG_KEY,
                    EapAkaConfigUtils.toPersistableBundle(config.getEapAkaConfig()));
        }

        if (config.getEapMsChapV2Config() != null) {
            result.putPersistableBundle(
                    EAP_MSCHAP_V2_CONFIG_KEY,
                    EapMsChapV2ConfigUtils.toPersistableBundle(config.getEapMsChapV2Config()));
        }

        if (config.getEapAkaPrimeConfig() != null) {
            result.putPersistableBundle(
                    EAP_AKA_PRIME_CONFIG_KEY,
                    EapAkaPrimeConfigUtils.toPersistableBundle(config.getEapAkaPrimeConfig()));
        }

        return result;
    }

    /** Constructs an EapSessionConfig by deserializing a PersistableBundle. */
    @NonNull
    public static EapSessionConfig fromPersistableBundle(@NonNull PersistableBundle in) {
        Objects.requireNonNull(in, "PersistableBundle was null");

        final EapSessionConfig.Builder builder = new EapSessionConfig.Builder();

        final PersistableBundle eapIdBundle = in.getPersistableBundle(EAP_ID_KEY);
        Objects.requireNonNull(eapIdBundle, "EAP ID was null");
        builder.setEapIdentity(PersistableBundleUtils.toByteArray(eapIdBundle));

        final PersistableBundle simBundle = in.getPersistableBundle(EAP_SIM_CONFIG_KEY);
        if (simBundle != null) {
            EapSimConfigUtils.setBuilderByReadingPersistableBundle(simBundle, builder);
        }

        final PersistableBundle ttlsBundle = in.getPersistableBundle(EAP_TTLS_CONFIG_KEY);
        if (ttlsBundle != null) {
            EapTtlsConfigUtils.setBuilderByReadingPersistableBundle(ttlsBundle, builder);
        }

        final PersistableBundle akaBundle = in.getPersistableBundle(EAP_AKA_CONFIG_KEY);
        if (akaBundle != null) {
            EapAkaConfigUtils.setBuilderByReadingPersistableBundle(akaBundle, builder);
        }

        final PersistableBundle msChapV2Bundle = in.getPersistableBundle(EAP_MSCHAP_V2_CONFIG_KEY);
        if (msChapV2Bundle != null) {
            EapMsChapV2ConfigUtils.setBuilderByReadingPersistableBundle(msChapV2Bundle, builder);
        }

        final PersistableBundle akaPrimeBundle = in.getPersistableBundle(EAP_AKA_PRIME_CONFIG_KEY);
        if (akaPrimeBundle != null) {
            EapAkaPrimeConfigUtils.setBuilderByReadingPersistableBundle(akaPrimeBundle, builder);
        }

        return builder.build();
    }

    private static class EapMethodConfigUtils {
        private static final String METHOD_TYPE = "METHOD_TYPE";

        /** Serializes an EapMethodConfig to a PersistableBundle. */
        @NonNull
        public static PersistableBundle toPersistableBundle(@NonNull EapMethodConfig config) {
            final PersistableBundle result = new PersistableBundle();
            result.putInt(METHOD_TYPE, config.getMethodType());
            return result;
        }
    }

    private static class EapUiccConfigUtils extends EapMethodConfigUtils {
        static final String SUB_ID_KEY = "SUB_ID_KEY";
        static final String APP_TYPE_KEY = "APP_TYPE_KEY";

        @NonNull
        protected static PersistableBundle toPersistableBundle(@NonNull EapUiccConfig config) {
            final PersistableBundle result = EapMethodConfigUtils.toPersistableBundle(config);
            result.putInt(SUB_ID_KEY, config.getSubId());
            result.putInt(APP_TYPE_KEY, config.getAppType());

            return result;
        }
    }

    private static final class EapSimConfigUtils extends EapUiccConfigUtils {
        @NonNull
        public static PersistableBundle toPersistableBundle(EapSimConfig config) {
            return EapUiccConfigUtils.toPersistableBundle(config);
        }

        public static void setBuilderByReadingPersistableBundle(
                @NonNull PersistableBundle in, @NonNull EapSessionConfig.Builder builder) {
            Objects.requireNonNull(in, "PersistableBundle was null");
            builder.setEapSimConfig(in.getInt(SUB_ID_KEY), in.getInt(APP_TYPE_KEY));
        }
    }

    private static class EapAkaConfigUtils extends EapUiccConfigUtils {
        @NonNull
        public static PersistableBundle toPersistableBundle(@NonNull EapAkaConfig config) {
            return EapUiccConfigUtils.toPersistableBundle(config);
        }

        public static void setBuilderByReadingPersistableBundle(
                @NonNull PersistableBundle in, @NonNull EapSessionConfig.Builder builder) {
            Objects.requireNonNull(in, "PersistableBundle was null");
            builder.setEapAkaConfig(in.getInt(SUB_ID_KEY), in.getInt(APP_TYPE_KEY));
        }
    }

    private static final class EapAkaPrimeConfigUtils extends EapAkaConfigUtils {
        private static final String NETWORK_NAME_KEY = "NETWORK_NAME_KEY";
        private static final String ALL_MISMATCHED_NETWORK_KEY = "ALL_MISMATCHED_NETWORK_KEY";

        @NonNull
        public static PersistableBundle toPersistableBundle(@NonNull EapAkaPrimeConfig config) {
            final PersistableBundle result = EapUiccConfigUtils.toPersistableBundle(config);
            result.putString(NETWORK_NAME_KEY, config.getNetworkName());
            result.putBoolean(ALL_MISMATCHED_NETWORK_KEY, config.allowsMismatchedNetworkNames());

            return result;
        }

        public static void setBuilderByReadingPersistableBundle(
                @NonNull PersistableBundle in, @NonNull EapSessionConfig.Builder builder) {
            Objects.requireNonNull(in, "PersistableBundle was null");
            builder.setEapAkaPrimeConfig(
                    in.getInt(SUB_ID_KEY),
                    in.getInt(APP_TYPE_KEY),
                    in.getString(NETWORK_NAME_KEY),
                    in.getBoolean(ALL_MISMATCHED_NETWORK_KEY));
        }
    }

    private static final class EapMsChapV2ConfigUtils extends EapMethodConfigUtils {
        private static final String USERNAME_KEY = "USERNAME_KEY";
        private static final String PASSWORD_KEY = "PASSWORD_KEY";

        @NonNull
        public static PersistableBundle toPersistableBundle(@NonNull EapMsChapV2Config config) {
            final PersistableBundle result = EapMethodConfigUtils.toPersistableBundle(config);
            result.putString(USERNAME_KEY, config.getUsername());
            result.putString(PASSWORD_KEY, config.getPassword());

            return result;
        }

        public static void setBuilderByReadingPersistableBundle(
                @NonNull PersistableBundle in, @NonNull EapSessionConfig.Builder builder) {
            Objects.requireNonNull(in, "PersistableBundle was null");
            builder.setEapMsChapV2Config(in.getString(USERNAME_KEY), in.getString(PASSWORD_KEY));
        }
    }

    private static final class EapTtlsConfigUtils extends EapMethodConfigUtils {
        private static final String TRUST_CERT_KEY = "TRUST_CERT_KEY";
        private static final String EAP_SESSION_CONFIG_KEY = "EAP_SESSION_CONFIG_KEY";

        @NonNull
        public static PersistableBundle toPersistableBundle(@NonNull EapTtlsConfig config) {
            final PersistableBundle result = EapMethodConfigUtils.toPersistableBundle(config);
            try {
                if (config.getServerCaCert() != null) {
                    final PersistableBundle caBundle =
                            PersistableBundleUtils.fromByteArray(
                                    config.getServerCaCert().getEncoded());
                    result.putPersistableBundle(TRUST_CERT_KEY, caBundle);
                }
            } catch (CertificateEncodingException e) {
                throw new IllegalStateException("Fail to encode the certificate");
            }

            result.putPersistableBundle(
                    EAP_SESSION_CONFIG_KEY,
                    EapSessionConfigUtils.toPersistableBundle(config.getInnerEapSessionConfig()));

            return result;
        }

        public static void setBuilderByReadingPersistableBundle(
                @NonNull PersistableBundle in, @NonNull EapSessionConfig.Builder builder) {
            Objects.requireNonNull(in, "PersistableBundle was null");

            final PersistableBundle caBundle = in.getPersistableBundle(TRUST_CERT_KEY);
            X509Certificate caCert = null;
            if (caBundle != null) {
                caCert =
                        CertUtils.certificateFromByteArray(
                                PersistableBundleUtils.toByteArray(caBundle));
            }

            final PersistableBundle eapSessionConfigBundle =
                    in.getPersistableBundle(EAP_SESSION_CONFIG_KEY);
            Objects.requireNonNull(eapSessionConfigBundle, "Inner EAP Session Config was null");
            final EapSessionConfig eapSessionConfig =
                    EapSessionConfigUtils.fromPersistableBundle(eapSessionConfigBundle);

            builder.setEapTtlsConfig(caCert, eapSessionConfig);
        }
    }
}
+143 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net.vcn.persistablebundleutils;

import static com.android.internal.annotations.VisibleForTesting.Visibility;

import android.annotation.NonNull;
import android.net.InetAddresses;
import android.net.ipsec.ike.IkeDerAsn1DnIdentification;
import android.net.ipsec.ike.IkeFqdnIdentification;
import android.net.ipsec.ike.IkeIdentification;
import android.net.ipsec.ike.IkeIpv4AddrIdentification;
import android.net.ipsec.ike.IkeIpv6AddrIdentification;
import android.net.ipsec.ike.IkeKeyIdIdentification;
import android.net.ipsec.ike.IkeRfc822AddrIdentification;
import android.os.PersistableBundle;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.vcn.util.PersistableBundleUtils;

import java.net.Inet4Address;
import java.net.Inet6Address;
import java.util.Objects;

import javax.security.auth.x500.X500Principal;

/**
 * Abstract utility class to convert IkeIdentification to/from PersistableBundle.
 *
 * @hide
 */
@VisibleForTesting(visibility = Visibility.PRIVATE)
public final class IkeIdentificationUtils {
    private static final String ID_TYPE_KEY = "ID_TYPE_KEY";

    private static final String DER_ASN1_DN_KEY = "DER_ASN1_DN_KEY";
    private static final String FQDN_KEY = "FQDN_KEY";
    private static final String KEY_ID_KEY = "KEY_ID_KEY";
    private static final String IP4_ADDRESS_KEY = "IP4_ADDRESS_KEY";
    private static final String IP6_ADDRESS_KEY = "IP6_ADDRESS_KEY";
    private static final String RFC822_ADDRESS_KEY = "RFC822_ADDRESS_KEY";

    private static final int ID_TYPE_DER_ASN1_DN = 1;
    private static final int ID_TYPE_FQDN = 2;
    private static final int ID_TYPE_IPV4_ADDR = 3;
    private static final int ID_TYPE_IPV6_ADDR = 4;
    private static final int ID_TYPE_KEY_ID = 5;
    private static final int ID_TYPE_RFC822_ADDR = 6;

    /** Serializes an IkeIdentification to a PersistableBundle. */
    @NonNull
    public static PersistableBundle toPersistableBundle(@NonNull IkeIdentification ikeId) {
        if (ikeId instanceof IkeDerAsn1DnIdentification) {
            final PersistableBundle result = createPersistableBundle(ID_TYPE_DER_ASN1_DN);
            IkeDerAsn1DnIdentification id = (IkeDerAsn1DnIdentification) ikeId;
            result.putPersistableBundle(
                    DER_ASN1_DN_KEY,
                    PersistableBundleUtils.fromByteArray(id.derAsn1Dn.getEncoded()));
            return result;
        } else if (ikeId instanceof IkeFqdnIdentification) {
            final PersistableBundle result = createPersistableBundle(ID_TYPE_FQDN);
            IkeFqdnIdentification id = (IkeFqdnIdentification) ikeId;
            result.putString(FQDN_KEY, id.fqdn);
            return result;
        } else if (ikeId instanceof IkeIpv4AddrIdentification) {
            final PersistableBundle result = createPersistableBundle(ID_TYPE_IPV4_ADDR);
            IkeIpv4AddrIdentification id = (IkeIpv4AddrIdentification) ikeId;
            result.putString(IP4_ADDRESS_KEY, id.ipv4Address.getHostAddress());
            return result;
        } else if (ikeId instanceof IkeIpv6AddrIdentification) {
            final PersistableBundle result = createPersistableBundle(ID_TYPE_IPV6_ADDR);
            IkeIpv6AddrIdentification id = (IkeIpv6AddrIdentification) ikeId;
            result.putString(IP6_ADDRESS_KEY, id.ipv6Address.getHostAddress());
            return result;
        } else if (ikeId instanceof IkeKeyIdIdentification) {
            final PersistableBundle result = createPersistableBundle(ID_TYPE_KEY_ID);
            IkeKeyIdIdentification id = (IkeKeyIdIdentification) ikeId;
            result.putPersistableBundle(KEY_ID_KEY, PersistableBundleUtils.fromByteArray(id.keyId));
            return result;
        } else if (ikeId instanceof IkeRfc822AddrIdentification) {
            final PersistableBundle result = createPersistableBundle(ID_TYPE_RFC822_ADDR);
            IkeRfc822AddrIdentification id = (IkeRfc822AddrIdentification) ikeId;
            result.putString(RFC822_ADDRESS_KEY, id.rfc822Name);
            return result;
        } else {
            throw new IllegalStateException("Unrecognized IkeIdentification subclass");
        }
    }

    private static PersistableBundle createPersistableBundle(int idType) {
        final PersistableBundle result = new PersistableBundle();
        result.putInt(ID_TYPE_KEY, idType);
        return result;
    }

    /** Constructs an IkeIdentification by deserializing a PersistableBundle. */
    @NonNull
    public static IkeIdentification fromPersistableBundle(@NonNull PersistableBundle in) {
        Objects.requireNonNull(in, "PersistableBundle was null");
        int idType = in.getInt(ID_TYPE_KEY);
        switch (idType) {
            case ID_TYPE_DER_ASN1_DN:
                final PersistableBundle dnBundle = in.getPersistableBundle(DER_ASN1_DN_KEY);
                Objects.requireNonNull(dnBundle, "ASN1 DN was null");
                return new IkeDerAsn1DnIdentification(
                        new X500Principal(PersistableBundleUtils.toByteArray(dnBundle)));
            case ID_TYPE_FQDN:
                return new IkeFqdnIdentification(in.getString(FQDN_KEY));
            case ID_TYPE_IPV4_ADDR:
                final String v4AddressStr = in.getString(IP4_ADDRESS_KEY);
                Objects.requireNonNull(v4AddressStr, "IPv4 address was null");
                return new IkeIpv4AddrIdentification(
                        (Inet4Address) InetAddresses.parseNumericAddress(v4AddressStr));
            case ID_TYPE_IPV6_ADDR:
                final String v6AddressStr = in.getString(IP6_ADDRESS_KEY);
                Objects.requireNonNull(v6AddressStr, "IPv6 address was null");
                return new IkeIpv6AddrIdentification(
                        (Inet6Address) InetAddresses.parseNumericAddress(v6AddressStr));
            case ID_TYPE_KEY_ID:
                final PersistableBundle keyIdBundle = in.getPersistableBundle(KEY_ID_KEY);
                Objects.requireNonNull(in, "Key ID was null");
                return new IkeKeyIdIdentification(PersistableBundleUtils.toByteArray(keyIdBundle));
            case ID_TYPE_RFC822_ADDR:
                return new IkeRfc822AddrIdentification(in.getString(RFC822_ADDRESS_KEY));
            default:
                throw new IllegalStateException("Unrecognized IKE ID type: " + idType);
        }
    }
}
+87 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading