001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * @author Vladimir N. Molotkov, Stepan M. Mishura
020: * @version $Revision$
021: */package org.apache.harmony.security.asn1;
022:
023: import java.io.IOException;
024:
025: import org.apache.harmony.security.internal.nls.Messages;
026:
027: /**
028: * Implicitly tagged ASN.1 type.
029: *
030: * @see http://asn1.elibel.tm.fr/en/standards/index.htm
031: */
032: public class ASN1Implicit extends ASN1Type {
033:
034: // primitive type of tagging
035: private static final int TAGGING_PRIMITIVE = 0;
036:
037: // constructed type of tagging
038: private static final int TAGGING_CONSTRUCTED = 1;
039:
040: // string type of tagging
041: private static final int TAGGING_STRING = 2;
042:
043: // tagged ASN.1 type
044: private final ASN1Type type;
045:
046: // type of tagging. There are three of them
047: // 1) primitive: only primitive identifier is valid
048: // 2) constructed: only constructed identifier is valid
049: // 3) string: both identifiers are valid
050: private final int taggingType;
051:
052: /**
053: * Constructs implicitly tagged ASN.1 type
054: * with context-specific tag class and specified tag number.
055: *
056: * @param tagNumber - ASN.1 tag number
057: * @param type - ASN.1 type to be tagged
058: * @throws IllegalArgumentException - if tagNumber or type is invalid
059: */
060: public ASN1Implicit(int tagNumber, ASN1Type type) {
061: this (CLASS_CONTEXTSPECIFIC, tagNumber, type);
062: }
063:
064: /**
065: * Constructs implicitly tagged ASN.1 type
066: *
067: * @param tagClass - ASN.1 tag class.
068: * @param tagNumber - ASN.1 tag number
069: * @param type - ASN.1 type to be tagged
070: * @throws IllegalArgumentException - if tagNumber, tagClass or type is invalid
071: */
072: public ASN1Implicit(int tagClass, int tagNumber, ASN1Type type) {
073: super (tagClass, tagNumber);
074:
075: if ((type instanceof ASN1Choice) || (type instanceof ASN1Any)) {
076: // According to X.680:
077: // 'The IMPLICIT alternative shall not be used if the type
078: // defined by "Type" is an untagged choice type or an
079: // untagged open type'
080: throw new IllegalArgumentException(Messages
081: .getString("security.9F")); //$NON-NLS-1$
082: }
083:
084: this .type = type;
085:
086: if (type.checkTag(type.id)) {
087: if (type.checkTag(type.constrId)) {
088: // the base encoding can be primitive ot constructed
089: // use both encodings
090: taggingType = TAGGING_STRING;
091: } else {
092: // if the base encoding is primitive use primitive encoding
093: taggingType = TAGGING_PRIMITIVE;
094: }
095: } else {
096: // if the base encoding is constructed use constructed encoding
097: taggingType = TAGGING_CONSTRUCTED;
098: }
099: }
100:
101: //
102: //
103: // Decode
104: //
105: //
106:
107: /**
108: * TODO
109: */
110: public final boolean checkTag(int identifier) {
111: switch (taggingType) {
112: case TAGGING_PRIMITIVE:
113: return id == identifier;
114: case TAGGING_CONSTRUCTED:
115: return constrId == identifier;
116: default: // TAGGING_STRING
117: return id == identifier || constrId == identifier;
118: }
119: }
120:
121: /**
122: * TODO
123: */
124: public Object decode(BerInputStream in) throws IOException {
125: if (!checkTag(in.tag)) {
126: // FIXME need look for tagging type
127: throw new ASN1Exception(Messages.getString("security.100", //$NON-NLS-1$
128: new Object[] { in.tagOffset,
129: Integer.toHexString(id),
130: Integer.toHexString(in.tag) }));
131: }
132:
133: // substitute indentifier for further decoding
134: if (id == in.tag) {
135: in.tag = type.id;
136: } else {
137: in.tag = type.constrId;
138: }
139: in.content = type.decode(in);
140:
141: if (in.isVerify) {
142: return null;
143: }
144: return getDecodedObject(in);
145: }
146:
147: //
148: //
149: // Encode
150: //
151: //
152:
153: public void encodeASN(BerOutputStream out) {
154: //FIXME need another way for specifying identifier to be encoded
155: if (taggingType == TAGGING_CONSTRUCTED) {
156: out.encodeTag(constrId);
157: } else {
158: out.encodeTag(id);
159: }
160: encodeContent(out);
161: }
162:
163: public void encodeContent(BerOutputStream out) {
164: type.encodeContent(out);
165: }
166:
167: public void setEncodingContent(BerOutputStream out) {
168: type.setEncodingContent(out);
169: }
170: }
|